@genex-ai/cli-demo 1.36.1 → 1.36.2
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.
package/README.md
CHANGED
|
@@ -103,7 +103,9 @@ built.
|
|
|
103
103
|
`.genex/scratch/cover.png` and the next `genex preview` (or `publish`) uploads
|
|
104
104
|
it, or run `genex cover <file>`. A CLI upload counts as the agent's pick — it
|
|
105
105
|
replaces anything picked automatically, never a cover the owner chose on the
|
|
106
|
-
dashboard — and a near-black or flat frame is refused with its numbers.
|
|
106
|
+
dashboard — and a near-black or flat frame is refused with its numbers. The
|
|
107
|
+
bundled `genex-cover` skill teaches the agent to choose or stage the game's
|
|
108
|
+
best real moment, judge candidates and send one.
|
|
107
109
|
|
|
108
110
|
Defaults: API `https://api.genex.games`, auth site
|
|
109
111
|
`https://genex.games` — override with `--api-url` / `--auth-url` (or
|
package/dist/index.js
CHANGED
|
@@ -891,19 +891,19 @@ Important note: put soul into your creations, with many details and love. Aim to
|
|
|
891
891
|
8. Never park ready work behind a question, and never stall on an unanswered one \u2014 decide, state the decision in chat, record it, keep building.
|
|
892
892
|
9. Before any publish and before ending a session: run \`npx genex wait\` on every generation you enqueued and wire in what landed \u2014 never park landed assets. Fonts the brief names are LOADED for real, Escape pauses, the loader shows something of the game rather than a black screen (the renderer draws before any \`await waitForPlayer()\` \u2014 identity takes seconds on a hosted page), and the player wears the game's own generated character (or DESIGN.md records why it doesn't).
|
|
893
893
|
10. The player's body is the game's own generated character (\`npx genex character "<look>"\` \u2192 \`npx genex controller character --character <id>\`), enqueued with your first art actions, not after them. It applies wherever a human body appears on screen \u2014 first-person included, the moment remotes, a look-down body, a shadow, or a menu portrait shows one. Games whose player is not a person (car, ship, RTS cursor, board) generate that object with \`npx genex model\` instead, or build it procedurally \u2014 held to law 22's bar like everything else the player looks at. Characters: Meshy/Mixamo/VRM rigs rest facing +Z. Set yaw explicitly when placing a rig; never mirror a SkinnedMesh with negative scale. In any two-character scene, verify in a capture that they face each other, not the camera.
|
|
894
|
-
11. Verify by looking: one smoke check per milestone, after that milestone's preview push, in local test mode (\`?genex_local_test=1\`) with a real gameplay screenshot. A claim without a capture is not verification. Local-test evidence proves visuals and controls ONLY \u2014 label it that way when you show the player, and never work around the draft sign-in gate any other way. These captures are also where the game's cover comes from: when one catches the game's signature moment, keep that frame as its cover (law 23).
|
|
894
|
+
11. Verify by looking: one smoke check per milestone, after that milestone's preview push, in local test mode (\`?genex_local_test=1\`) with a real gameplay screenshot. A claim without a capture is not verification. Local-test evidence proves visuals and controls ONLY \u2014 label it that way when you show the player, and never work around the draft sign-in gate any other way. These captures are also where the game's cover comes from: when one catches the game's signature moment, keep that frame as its cover (law 23) \u2014 and \`$genex-cover\` stages and judges the best one the game has.
|
|
895
895
|
12. Treat every \`genex\` warning line \u2014 preflight, \`ui audit\`, \`wait\` nudges \u2014 as work, not noise.
|
|
896
896
|
13. Every finished Build-plan milestone ends with \`npx genex preview\` and the player's page link (\`<dashboard>/draft/<slug>\`, with \`<dashboard>\` from \`.genex/project.json\`) \u2014 never a localhost link, a file path, or the bare play origin presented as their game. That page shows the build you just previewed; \`preview\` never disturbs the build players are on. When the player is happy with it, \`npx genex promote\` makes that exact build live for everyone \u2014 no rebuild. After every round of player feedback, end with a preview push. After the first release, the game is two versions and the player only ever hears these two words for them: the **draft** (their working copy, updated by \`preview\`) and the **public version** (what everyone plays). Command names are yours, not theirs \u2014 never say "promote" to the player; ask directly: "Want me to update the public version?", one line, once per round, and keep building while you wait \u2014 updating the public version is the ONE action that waits for an explicit yes, and more change requests instead of a yes mean "not yet". The player's "publish it" / "publish the update" / "update it" / "yes" after the first release ALL mean \`genex promote\` \u2014 never \`genex publish\` again, which would ship an untried rebuild. \`promote\` ships the last previewed build, so if anything was edited since the last \`preview\`, preview again before promoting.
|
|
897
897
|
14. Parallel work: this line is your standing authorization and request to use sub-agents / parallel agent work whenever your platform provides them. While drafting the Build plan, decide per module what runs in parallel and what stays serial for THIS game \u2014 dependencies decide, there is no fixed list \u2014 and record each call in the Modules table with a one-line reason. Independent modules default to parallel; building everything serially needs a stated reason. You keep integration, previews, and the player conversation; each sub-agent owns only its module's files. When the player asks for parallel work, repeated refinement passes, a critic reviewing your output, or names any way of working your platform provides, that IS your instruction \u2014 wherever it reaches you, including inside their answer to a question you asked \u2014 so adopt it as the working mode for the rest of the build, starting with the work in front of you, and never file it as a later milestone. While delegated work runs, keep building or talk to the player; never idle in a foreground wait for something your platform will tell you about.
|
|
898
898
|
15. Talk to the player in plain game language \u2014 what changed in the game and what to try; never code, file names, build output, or tool internals unless they ask. Short status lines while you work; long silent stretches are a failure.
|
|
899
|
-
16. Never add debug-only code that fakes gameplay \u2014 no hidden test modes, special URL parameters, forced-visible flags or auth mocks. The visual-validation skill permits a development-only final-mix analyser for a deliberately triggered audible event; remove it from published builds. \`?genex_local_test=1\` is the platform's own supported mode and is fine; your own bypass is not. (The multiplayer skill's small build identifier, token-free status line, and connected-quorum watchdog are production supportability, not a bypass \u2014 keep those.)
|
|
899
|
+
16. Never add debug-only code that fakes gameplay \u2014 no hidden test modes, special URL parameters, forced-visible flags or auth mocks. The visual-validation skill permits a development-only final-mix analyser for a deliberately triggered audible event; remove it from published builds. The \`genex-cover\` skill's development-only cover shot (\`?cover=<name>\` on the dev server) is a camera, not a bypass: it never reaches a published build, never touches sign-in, saves or progress, and is never evidence that the game works. \`?genex_local_test=1\` is the platform's own supported mode and is fine; your own bypass is not. (The multiplayer skill's small build identifier, token-free status line, and connected-quorum watchdog are production supportability, not a bypass \u2014 keep those.)
|
|
900
900
|
17. Input directions match their labels: A/\u2190 moves or turns the player screen-LEFT, D/\u2192 screen-RIGHT, mouse-up looks up, and drag-pan axes share ONE convention. The cursor is either the gameplay tool (RTS, card, builder) or locked away during play \u2014 keyboard-only games included. Check it in every milestone's smoke pass.
|
|
901
901
|
18. NEVER delete, empty, move, rename, or overwrite anything you did not create yourself. This folder may hold the player's own reference images, notes, sketches, or an earlier attempt \u2014 files that exist nowhere else and have no undo, no trash, no backup. A non-empty folder is normal and is NEVER something to clean up, and "start clean" is never a reason. That rules out \`rm\`/\`rm -rf\`, \`git clean\`, \`git checkout -- .\`, \`git reset --hard\` over their work, deleting to resolve a conflict or a stuck interactive prompt, and every setup tool's offer to empty a directory (\`--force\`, \`--overwrite\`, "Remove existing files") \u2014 scaffold into a fresh subfolder and copy in instead. You may add files and edit the ones you wrote. If a step genuinely cannot continue without removing something of theirs, STOP and ask, naming the exact files, and wait for a yes \u2014 "it looks like junk" is never that yes. This binds hardest during setup, where it runs fast and automatically before the player has asked for anything at all.
|
|
902
902
|
19. If the game sells anything, it sells it for coin at a fixed, visible price, and NEVER sells chance. Run this test on any purchasable thing before building it: does the player pay (with coin, or with anything coin bought, directly or indirectly), is the outcome uncertain when they pay, and is there a prize they wanted \u2014 all three yes means it is paid randomness, and you build the deterministic version instead. That rules out loot boxes, gacha, mystery boxes, crates, card packs, prize wheels and raffles; wagering, staking, betting, coinflips and casino or slot mechanics denominated in coin; and donation prompts, tip jars or any player-to-player coin transfer, because coin buys goods and never just moves. Randomness the player EARNS by playing is gameplay, not commerce \u2014 an enemy dropping a random item, a chest found in the level, a procedural layout, a crit roll \u2014 and is completely fine. Every coin price renders its real-money equivalent beside it (the server sends one with every item), item prices sit on the platform's price grid so no player is left holding change they cannot spend, and nothing in a shop carries a countdown, "limited time", or a stock counter. When a request crosses one of these lines, name the mechanic, give the one-sentence reason, propose a specific compliant alternative, and build that \u2014 never the banned version "as an option", never a partial one, and never after asking the player to confirm they want it. Load \`$genex-monetization\` before building a shop.
|
|
903
903
|
20. When the player names a specific thing to integrate \u2014 a library, a controller, an asset, a part of an existing game, or a tagged reference the platform placed in \`.genex/refs/<slug>/\` \u2014 integrate the real thing: read its source first and build from it, never a lighter look-alike written from scratch because it was faster. A tagged reference owns the subsystem it was tagged for, outranking the default lane and the vendored controllers for that subsystem. If you genuinely can't use it, say so in one plain line and ask how to proceed.
|
|
904
904
|
21. A turn ends in exactly one of two ways: on a question the player must answer before the next step can be chosen, or on a handoff \u2014 the draft link, what changed, what to try, and what is still open. Never close a turn on a promise. "I'll keep building", "while I keep working", "adding that now" are things you say and then DO before you stop; if you are stopping, say that you have stopped and what remains. While the Build plan's \`Now:\` line has open work and no answer is needed from the player, the turn is not over: preview, hand off, and start the next milestone in the same turn, until the requested outcome is reached or the platform's own budget ends the session. If a stop was forced on you anyway, the first line of your next turn is the promise you left and where it stands.
|
|
905
905
|
22. **What the player sees must read as the thing it is**, in this game's own style: a building as that building, a person as a person, a prop as that prop, a surface as its material \u2014 and a coloured box, a capsule, or a flat grey block standing in for one of them is never its finished version. Generation is the default route to that bar wherever code will not honestly reach it: the player's character, whatever the request names, whatever the player walks up to, enters, or interacts with, and the music and sound underneath \u2014 reach for the belt on your own judgment, without stopping to ask; a status line saying what you queued is enough, and \`--no-wait\` keeps you building while it lands. Procedural code is a first-class engine for what is structural, repeated, distant, or parametric \u2014 terrain, sky, fences, paving, modular kits, filler \u2014 and for anything else only when the result meets the same bar and you have looked at it in a capture before its row says \`landed\`. Start with one reusable implementation per distinct required gameplay or visual role. Background populations default to reusable procedural bodies and motion or compatible existing rigged assets. Catalog clips need a compatible skeleton and may be paid. Reserve paid custom bodies for the player and characters examined or interacted with closely, while honoring explicit user requests. Add variants only for an unmet requirement; unspent allowance is not unfinished work. Allowance questions use timeoutPolicy no-consent: silence does not raise the allowance. Record role, reuse and completion criteria in the existing Assets table. Decide per object, not per category, and write the route on each Assets row in \`DESIGN.md\` \u2014 the paid flow for generated pieces, the procedural flow with its local path for code-built ones. An Assets table with no generation in it is a decision, not a default: record it as \`Generation: none \u2014 <why code alone reaches the bar here>\` or generate.
|
|
906
|
-
23. **The screenshots you take to look at your own work go in \`.genex/scratch/\`.** Captures, render comparisons, before/after strips, traces and metrics dumps are how you SEE what you built \u2014 they are not part of what you built, and \`genex preview\` pushes the whole folder to the game's source, every time, forever. \`.genex/scratch/\` already exists for this and is already ignored, so there is nothing to set up: write the capture as \`.genex/scratch/arena-before.png\` and read it back from there. Never put them in a folder of your own at the top level: \`progress/\`, \`reports/\`, \`shots/\` and their kind are pushed like source and become permanent weight in the game and in every remix of it \u2014 one real game reached 11 GB and 10,332 committed screenshots exactly this way. If you find such a folder already there, add it to \`.gitignore\`; never delete the player's files (law 18). One file in \`.genex/scratch/\` IS read, by the platform: \`.genex/scratch/cover.png\` is the game's cover \u2014 the frame you would put on its poster: real gameplay at its signature moment, well lit, no menus, popups or busy HUD, landscape 16:9, and never any text (the page sets the title beside it). The next \`genex preview\` makes it the cover; save a better moment over it whenever one comes along, and if your browser tool can set the cover itself, use that instead.
|
|
906
|
+
23. **The screenshots you take to look at your own work go in \`.genex/scratch/\`.** Captures, render comparisons, before/after strips, traces and metrics dumps are how you SEE what you built \u2014 they are not part of what you built, and \`genex preview\` pushes the whole folder to the game's source, every time, forever. \`.genex/scratch/\` already exists for this and is already ignored, so there is nothing to set up: write the capture as \`.genex/scratch/arena-before.png\` and read it back from there. Never put them in a folder of your own at the top level: \`progress/\`, \`reports/\`, \`shots/\` and their kind are pushed like source and become permanent weight in the game and in every remix of it \u2014 one real game reached 11 GB and 10,332 committed screenshots exactly this way. If you find such a folder already there, add it to \`.gitignore\`; never delete the player's files (law 18). One file in \`.genex/scratch/\` IS read, by the platform: \`.genex/scratch/cover.png\` is the game's cover \u2014 the frame you would put on its poster: real gameplay at its signature moment, well lit, no menus, popups or busy HUD, landscape 16:9, and never any text (the page sets the title beside it). The next \`genex preview\` makes it the cover; save a better moment over it whenever one comes along, and if your browser tool can set the cover itself, use that instead. Before the first publish, and whenever the game's look changes, load \`$genex-cover\`: it chooses, stages, lights and judges that frame.
|
|
907
907
|
24. **Benchmark before declaring an in-game LLM price.** If the game calls a language model while the player plays \u2014 an NPC answering in its own words, a quest written for this save, a judge reading what the player typed \u2014 the PLAYER pays for it, and \`estimateCoins\` is the FIXED price of a started attempt: charged whether it succeeds, fails, is canceled, or stops at its own budget. Never pick that number by judgement or from a vendor's rate card. Run the real prompt on your own coins \u2014 \`npx genex llm bench "<the prompt>" --schema <file> --samples 3 --max-coins <n> --user-approved\` \u2014 and declare the figure it recommends, recorded in \`DESIGN.md\` with its model and date; re-benchmark whenever the prompt, the schema or the model changes, because a prompt edit is a price change. Check the lane first with \`npx genex llm models\`: where it is off the routes 404, so build the feature behind a graceful unavailable state and say so in the handoff. A repeated call is a standing budget the player approves once (\`requestSpendGrant()\`, then \`generate({ grantId })\`), never a popup per turn, and its disclosed call rate is computed from the game's own loop. Model output is data the game validates against its own expectation \u2014 never executed, and never authority over coin, items, entitlements or rewards. Load \`$genex-llm-in-games\` before writing any of it.
|
|
908
908
|
${CONTRACT_END}
|
|
909
909
|
`;
|
|
@@ -944,7 +944,7 @@ This is a separate game prepared from source. The user's request decides what to
|
|
|
944
944
|
- Edit the existing implementation as the request needs. Preserve unrelated files and never empty a destination to make room. Keep required source credits and license notices in source files, LICENSE/NOTICE, README or metadata; Genex does not require an in-game credit overlay. Follow any specific display obligation actually required by the source license.
|
|
945
945
|
- Keep platform boot correct: call initEmbed() before platform APIs and render before awaiting player identity. The genex-threejs-embed-auth specialist explains the glue. Collect every generation you start with genex wait and use the result before handing off; do not run empty generation checks.
|
|
946
946
|
- Preview through npx genex preview and share the actual draft page. Preparing source creates a placeholder page; only a successful preview puts a playable build there. Public release remains a separate user decision: publish for the first release, promote for a previewed update. Use a plan and specialist skills in proportion to the requested work.
|
|
947
|
-
- Check the requested result in gameplay. A successful build or HUD label alone proves no gameplay. Use one bounded smoke check; if the browser cannot observe/render the game after a reasonable retry, explain exactly what remains unverified rather than repeating timeouts or claiming success. Supported loopback ?genex_local_test=1 checks visuals and controls only; do not invent auth bypasses or debug-only game paths.
|
|
947
|
+
- Check the requested result in gameplay. A successful build or HUD label alone proves no gameplay. Use one bounded smoke check; if the browser cannot observe/render the game after a reasonable retry, explain exactly what remains unverified rather than repeating timeouts or claiming success. Supported loopback ?genex_local_test=1 checks visuals and controls only; do not invent auth bypasses or debug-only game paths (the genex-cover specialist's development-only \`?cover=<name>\` cover shot is a camera, not one: it never reaches a published build and proves nothing about gameplay).
|
|
948
948
|
- Give short progress updates in plain game language. After resume or compaction, re-read this block and the latest request, then continue that work. The source's old style and mechanics are choices, not obligations.
|
|
949
949
|
${CONTRACT_END}
|
|
950
950
|
`;
|
|
@@ -1239,7 +1239,8 @@ var TOOL_SKILL_PREFIX = "genex-tool-";
|
|
|
1239
1239
|
var HOSTED_TOOL_SKILLS = [
|
|
1240
1240
|
"genex-tool-publish",
|
|
1241
1241
|
"genex-threejs-embed-auth",
|
|
1242
|
-
"genex-llm-in-games"
|
|
1242
|
+
"genex-llm-in-games",
|
|
1243
|
+
"genex-cover"
|
|
1243
1244
|
];
|
|
1244
1245
|
var REMIX_EXCLUDED_SKILLS = [
|
|
1245
1246
|
"genex-game-director",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genex-ai/cli-demo",
|
|
3
|
-
"version": "1.36.
|
|
3
|
+
"version": "1.36.2",
|
|
4
4
|
"description": "Set up your project's agent workspace (.claude/.codex/.cursor in the game folder), authorize, create a game project, generate AI assets, and publish (genex CLI).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: genex-cover
|
|
3
|
+
description: Make this game's cover — the one real frame its gallery card, game page and every shared link show. Choose or stage its best moment from its own world, models, light and effects (the hero, the action at its peak, the best-lit angle; no HUD, no text, 16:9), shoot several candidates, judge them at card size and send the best. Load once the game looks like itself, before its first publish, and again when its look changes.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Genex · Cover
|
|
7
|
+
|
|
8
|
+
The cover is the game's poster: the picture on its gallery card, at the top of
|
|
9
|
+
its page and on every link anyone shares — often all a stranger sees before
|
|
10
|
+
deciding to play. It is **one real render of this game**: its own world,
|
|
11
|
+
models, light and effects, drawn by its own renderer. You built that world, so
|
|
12
|
+
you are best placed to find the frame a player would screenshot and send to a
|
|
13
|
+
friend. The craft is yours; the boundaries are not. The `$genex-*` skills
|
|
14
|
+
linked below go deeper; where one is not installed, this page stands alone.
|
|
15
|
+
|
|
16
|
+
## When
|
|
17
|
+
|
|
18
|
+
- **Make it** once the game looks like itself: the core loop plays, the hero
|
|
19
|
+
and the world wear their real assets (no stand-in boxes), the light and grade
|
|
20
|
+
are settled. Usually at a milestone's smoke check; always before the first
|
|
21
|
+
publish.
|
|
22
|
+
- **Refresh it** when the look changes — a new hero, art direction, lighting,
|
|
23
|
+
level or effect that is now the game's best moment — or when the cover shows
|
|
24
|
+
something the game no longer has.
|
|
25
|
+
- **Not** every turn, not after fixes, tuning, audio or copy.
|
|
26
|
+
- **Check who holds it first** (the lane section says how). Chosen by the
|
|
27
|
+
owner: stop, that choice stands. Captured while the owner played: replace it
|
|
28
|
+
only with a clearly better frame. None, a stand-in picked automatically, or
|
|
29
|
+
your own earlier pick: make it better.
|
|
30
|
+
|
|
31
|
+
Your pick outranks every automatic cover and nothing automatic ever replaces
|
|
32
|
+
it, so a frame from the placeholder era would stick. Wait until the game is
|
|
33
|
+
worth it, and refresh it yourself when the game outgrows it.
|
|
34
|
+
|
|
35
|
+
## The honest frame — staging is photography
|
|
36
|
+
|
|
37
|
+
Stage freely; staging only chooses among what the game already has:
|
|
38
|
+
|
|
39
|
+
- the camera's place, height, lens and angle anywhere in the world, views play
|
|
40
|
+
never uses included — lower, closer, a longer lens — while still saying what
|
|
41
|
+
the player does: a game played from above is shot from above, just lower and
|
|
42
|
+
closer, and where the projection IS the look (isometric, side-on, a board),
|
|
43
|
+
keep it and move within it;
|
|
44
|
+
- a place, time of day and weather the game really has;
|
|
45
|
+
- the cast in the game's own animations, frozen on their strongest frame;
|
|
46
|
+
enemies the game really puts there, in numbers play really reaches;
|
|
47
|
+
- the game's own effects at their peak, physics settled, its top quality
|
|
48
|
+
setting;
|
|
49
|
+
- everything on top of the world removed: HUD, menus, prompts, popups, cursor,
|
|
50
|
+
reticle, aim cue, nameplates, touch controls, the sign-in gate, loading
|
|
51
|
+
screens, debug helpers.
|
|
52
|
+
|
|
53
|
+
Never:
|
|
54
|
+
|
|
55
|
+
- **text of any kind** — title, logo, caption, watermark, border. Every surface
|
|
56
|
+
already prints the title beside the cover or over its bottom edge, and a title
|
|
57
|
+
in the picture goes stale on a rename. Big lettering in the world reads as a
|
|
58
|
+
title too: frame it out.
|
|
59
|
+
- **a picture that is not a render of this game** — generated or painted art,
|
|
60
|
+
the menu's own generated key art, concept sheets, stock, another game.
|
|
61
|
+
- **anything the game does not have** — a model, effect, sky or place made for
|
|
62
|
+
the poster; an extra light on the hero; exposure, grading, bloom or depth of
|
|
63
|
+
field the game does not run.
|
|
64
|
+
- **changing the place** — hiding, moving or deleting its walls, props or
|
|
65
|
+
foliage, or thinning the fog, darkness or weather it has there. Move the
|
|
66
|
+
camera, never the set: only the cast and effects are posed, and only overlays
|
|
67
|
+
are removed.
|
|
68
|
+
- **brightening or relighting a game that is dark by design.** Choose its
|
|
69
|
+
best-lit honest moment — the lantern, the muzzle flash, the dawn it really
|
|
70
|
+
has; if even a tight frame on that moment is refused as too dark, stop and
|
|
71
|
+
leave the cover to the owner.
|
|
72
|
+
- **editing the pixels after capture** — no retouch, composite, crop or
|
|
73
|
+
upscale; re-shoot instead. Re-encoding a heavy PNG as JPEG is not editing.
|
|
74
|
+
|
|
75
|
+
The honesty test: a player who clicks this card can find this place, this
|
|
76
|
+
light and this kind of moment in the game.
|
|
77
|
+
|
|
78
|
+
The cover shot is a camera, not a cheat: players never meet it, it never
|
|
79
|
+
touches sign-in, saves, scores or progress, and a capture from it never proves
|
|
80
|
+
the game works — that evidence still comes from real play.
|
|
81
|
+
|
|
82
|
+
## 1. Choose the moment
|
|
83
|
+
|
|
84
|
+
One idea per frame — the strongest the game has, and the one the brief's mood
|
|
85
|
+
words promise: **its signature verb mid-action** (the jump at its apex, the
|
|
86
|
+
drift through the corner, the spell leaving the hand), **the hero at their most
|
|
87
|
+
characterful**, **the best vista**, or **the climax**. Not the spawn point, not
|
|
88
|
+
the default view of the player's back, not a moment with nothing happening.
|
|
89
|
+
|
|
90
|
+
| Game | Starting shot |
|
|
91
|
+
| --- | --- |
|
|
92
|
+
| Racer, vehicle | low 3/4 front at wheel height, crossing into open road, dust or sparks caught |
|
|
93
|
+
| Third-person action | 3/4 front or over the shoulder, mid-action, the world opening behind |
|
|
94
|
+
| Top-down, twin-stick, isometric | the game's own angle, lower and closer, the hero mid-fire, the shots or blast leading the eye, enemies closing |
|
|
95
|
+
| First-person | down the sightline at the moment of action, tool in frame, target lit |
|
|
96
|
+
| Platformer | the hero at the apex, the gap and the next ledge readable, the vista behind |
|
|
97
|
+
| Flight, space | the craft banking, rim-lit against a planet, sun or nebula |
|
|
98
|
+
| Strategy, builder, sim | high oblique, 30–45° down, over the busiest best-lit district |
|
|
99
|
+
| Puzzle, board, cards | the board at its most dramatic state (a cascade, the winning move) in the game's own projection, closer; tilt a 3D board only as far as play already views it |
|
|
100
|
+
| Horror, dark | close on the one lit thing (the lantern pool, the torch cone, the lit doorway) so it fills at least a third of the frame; a small light in a wide black frame is refused as too dark |
|
|
101
|
+
| Multiplayer | bodies the game itself draws (its bots or NPCs) in one shared action, or one player's best moment — never invented remote players, never names |
|
|
102
|
+
|
|
103
|
+
## 2. Compose
|
|
104
|
+
|
|
105
|
+
Rigs and lens mechanics, where installed: `$genex-threejs-camera-direction`.
|
|
106
|
+
The poster rules:
|
|
107
|
+
|
|
108
|
+
- **16:9 from the first try** — the camera's aspect and the drawing buffer both
|
|
109
|
+
(the shot below). Anything else is centre-cropped to 16:9; a portrait frame
|
|
110
|
+
keeps only a thin band.
|
|
111
|
+
- **One subject, readable small** — most people see the cover a few hundred
|
|
112
|
+
pixels wide among dozens, six times smaller than a 1080p frame. The card-size
|
|
113
|
+
test: the subject spans at least a third of the frame's height and its
|
|
114
|
+
silhouette reads against its ground; if not, it is not the cover.
|
|
115
|
+
- **Thirds and lead room** — the subject on a third, eyes on the upper third,
|
|
116
|
+
space ahead of the face and the travel. Keep it clear of the corners and the
|
|
117
|
+
bottom edge: Genex cards set badges and a menu in the corners and darken the
|
|
118
|
+
bottom ones, and one surface prints the title along the bottom.
|
|
119
|
+
- **Three planes** — a darker partial foreground edge, the subject, depth or sky
|
|
120
|
+
behind; lines the world already has (road, wall, river, beam) lead to the
|
|
121
|
+
subject.
|
|
122
|
+
- **Height and lens** — low makes heroes and machines powerful; high oblique
|
|
123
|
+
explains a world. Three.js `fov` is vertical: about 25–40° for a hero or
|
|
124
|
+
vehicle (step back to keep the framing), 55–75° for a vista or speed. Horizon
|
|
125
|
+
level; tilt at most 10°, and only for speed or chaos.
|
|
126
|
+
- **Clean silhouette** — the subject against a ground of a different value,
|
|
127
|
+
nothing growing out of its head, no edge just touching another edge or the
|
|
128
|
+
frame. Characters face their target, or three-quarters to the camera — never
|
|
129
|
+
staring into the lens.
|
|
130
|
+
- **Colour with intent** — one accent on the subject that the background lacks;
|
|
131
|
+
the palette at its richest honest moment.
|
|
132
|
+
|
|
133
|
+
## 3. Light — the game's own
|
|
134
|
+
|
|
135
|
+
You choose when and where; you never add.
|
|
136
|
+
|
|
137
|
+
- **Key from the side or behind** — turn the camera until the game's sun or key
|
|
138
|
+
light sits well off the lens axis, or behind the subject as a rim. Front light
|
|
139
|
+
reads flat. Move the camera, not the sun.
|
|
140
|
+
- **Time and weather it really reaches** — with a day cycle or weather, take its
|
|
141
|
+
lowest, warmest or most dramatic phase; a fixed sun stays where it is.
|
|
142
|
+
- **Effects are light** — engine glow, spell, neon, lava, muzzle flash: catch
|
|
143
|
+
them at their peak, lighting the subject.
|
|
144
|
+
- **Exposure** — a bright subject in a darker surround, detail in its shadows,
|
|
145
|
+
no clipped sky. Meter it against the gate itself, never by eye: sRGB luma
|
|
146
|
+
`(0.2126R + 0.7152G + 0.0722B) / 255` over the whole 16:9 frame — its mean,
|
|
147
|
+
its spread (std) and its share below 0.10 (the shot below returns all three).
|
|
148
|
+
Where the game's light allows, aim well clear of the gate's lines — a frame
|
|
149
|
+
that only just passes reads murky on a card: mean 0.2 or more, std 0.08 or
|
|
150
|
+
more, under 70% near-black. (The playability meter in
|
|
151
|
+
`$genex-threejs-exposure-color-grading` is centre-weighted, a different test.)
|
|
152
|
+
|
|
153
|
+
## 4. Build the cover shot
|
|
154
|
+
|
|
155
|
+
Hunting for a great frame while playing is luck. Build it once as a **named
|
|
156
|
+
cover shot** — a small function that stages one moment from the game's own
|
|
157
|
+
parts and holds it — and the exact frame can be re-taken after every visual
|
|
158
|
+
change. Build two to four, across at least two ideas — the action and the
|
|
159
|
+
vista. If your host gives games named cameras or scripted demos, a cover shot
|
|
160
|
+
is one of each.
|
|
161
|
+
|
|
162
|
+
A cover shot:
|
|
163
|
+
|
|
164
|
+
1. loads its place and waits until everything in view is at full detail;
|
|
165
|
+
2. sets the game's own time of day and weather;
|
|
166
|
+
3. poses the cast with the game's own clips, every other action on that mixer
|
|
167
|
+
stopped — one left playing blends into the pose at equal weight
|
|
168
|
+
(`mixer.stopAllAction(); const a = mixer.clipAction(clip).reset().setEffectiveWeight(1).play(); a.time = t; a.paused = true; mixer.update(0)`),
|
|
169
|
+
each facing its target;
|
|
170
|
+
4. fires the game's own effect, advances it to its peak and settles the
|
|
171
|
+
physics, then stops the game clock while rendering goes on;
|
|
172
|
+
5. hides every overlay and the cursor;
|
|
173
|
+
6. sets the camera, then a 16:9 drawing buffer the size of the capture —
|
|
174
|
+
1920×1080 unless your lane captures a fixed smaller view — whatever the
|
|
175
|
+
window is:
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
camera.position.set(4.2, 1.1, 6.8);
|
|
179
|
+
camera.lookAt(0, 1.4, 0);
|
|
180
|
+
camera.fov = 35;
|
|
181
|
+
camera.aspect = 16 / 9;
|
|
182
|
+
// An OrthographicCamera has neither: keep its height and widen it to 16:9 instead —
|
|
183
|
+
// const h = (camera.top - camera.bottom) / 2; camera.left = -h * 16 / 9; camera.right = h * 16 / 9;
|
|
184
|
+
camera.updateProjectionMatrix();
|
|
185
|
+
renderer.setPixelRatio(1);
|
|
186
|
+
renderer.setSize(1920, 1080, false); // false: the page layout stays as it is
|
|
187
|
+
composer?.setPixelRatio(1); // the post stack, if the game runs one
|
|
188
|
+
composer?.setSize(1920, 1080);
|
|
189
|
+
renderer.shadowMap.needsUpdate = true; // a cached shadow map still shows the old pose
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
7. renders a few frames so temporal effects settle (snap eye adaptation to its
|
|
193
|
+
target rather than waiting it out), renders once more and meters that frame
|
|
194
|
+
in the same task — a WebGL buffer is cleared once a frame is shown — then
|
|
195
|
+
signals that the frame is held, with its numbers:
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
// The gate's own meter (§3). Call it right after the render, never later.
|
|
199
|
+
function meter(canvas: HTMLCanvasElement) {
|
|
200
|
+
const small = Object.assign(document.createElement("canvas"), { width: 160, height: 90 });
|
|
201
|
+
const ctx = small.getContext("2d", { willReadFrequently: true })!;
|
|
202
|
+
ctx.drawImage(canvas, 0, 0, 160, 90);
|
|
203
|
+
const px = ctx.getImageData(0, 0, 160, 90).data;
|
|
204
|
+
let sum = 0, sq = 0, dark = 0;
|
|
205
|
+
for (let i = 0; i < px.length; i += 4) {
|
|
206
|
+
const y = (0.2126 * px[i]! + 0.7152 * px[i + 1]! + 0.0722 * px[i + 2]!) / 255;
|
|
207
|
+
sum += y; sq += y * y; if (y < 0.1) dark++;
|
|
208
|
+
}
|
|
209
|
+
const n = px.length / 4, mean = sum / n;
|
|
210
|
+
return { mean, std: Math.sqrt(Math.max(0, sq / n - mean * mean)), dark: dark / n };
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Hold the extreme of the pose, never the in-between: feet planted or clearly
|
|
215
|
+
airborne, particles fanned out but not yet fading, the flash just past its
|
|
216
|
+
white-out. No camera shake, hit-stop flash, fade, motion-blur smear or
|
|
217
|
+
half-loaded texture.
|
|
218
|
+
|
|
219
|
+
What ruins a staged shot:
|
|
220
|
+
|
|
221
|
+
- **Something writes it back next frame** — the camera rig, the resize handler,
|
|
222
|
+
the quality governor, the character controller. Stop each while the shot is
|
|
223
|
+
held.
|
|
224
|
+
- **A low quality tier.** A game that picks a quality tier at boot (Genex's
|
|
225
|
+
adaptive-quality kit does: `$genex-threejs-adaptive-quality`) picks it before
|
|
226
|
+
the renderer exists: a browser rendering on the CPU boots as a weak desktop —
|
|
227
|
+
no antialiasing, smaller shadows, lighter post, fewer particles — and a
|
|
228
|
+
runtime governor steps slow frames further down. Antialiasing is fixed when
|
|
229
|
+
the context is created, so the shot boots at the full tier (the kit's
|
|
230
|
+
`TIERS.desktop`, what its Quality picker's High forces) and holds the
|
|
231
|
+
governor.
|
|
232
|
+
- **Shadows and near planes** — a shadow that follows the player still covering
|
|
233
|
+
where the player was; a near plane clipping a close foreground object.
|
|
234
|
+
- **A defect in frame** — a limb through the body or weapon, a T-pose,
|
|
235
|
+
z-fighting, a texture still on its low rung. That is a game bug: fix the game,
|
|
236
|
+
never hide it from the camera (`$genex-threejs-visual-validation`).
|
|
237
|
+
- **A sky drawn in CSS behind a transparent canvas** — transparency is flattened
|
|
238
|
+
onto black, and a canvas readback never sees the CSS. Draw the sky in the
|
|
239
|
+
scene, or capture the page as shown.
|
|
240
|
+
|
|
241
|
+
**A game kept as it is.** When the code is its owner's to keep untouched — you
|
|
242
|
+
were asked to publish a game, not change it — build nothing: take the frame
|
|
243
|
+
from play, stage from the browser console at most, and add no code for a poster.
|
|
244
|
+
|
|
245
|
+
## 5. Shoot, judge, keep one
|
|
246
|
+
|
|
247
|
+
Shoot every named shot, then two or three variants of the best: a step closer
|
|
248
|
+
or lower, a few frames earlier. Look at each at full size for defects, then
|
|
249
|
+
against the card-size test (§2) and its meter (§3), and score:
|
|
250
|
+
|
|
251
|
+
1. It says what the game is — genre and verb — at a glance.
|
|
252
|
+
2. One clear subject that reads at card size.
|
|
253
|
+
3. The light sculpts it; it separates from the ground.
|
|
254
|
+
4. Depth: foreground, subject, background.
|
|
255
|
+
5. Only the world on screen — no interface, no text.
|
|
256
|
+
6. Everything in it is something a player of this game sees.
|
|
257
|
+
7. Its meter reads well clear of the gate below.
|
|
258
|
+
8. Clean: no clipping, popping, jagged edges or missing textures.
|
|
259
|
+
|
|
260
|
+
Keep the best. If none passes 1–6, change the moment or the camera — never the
|
|
261
|
+
game. Then ask: would someone scrolling a gallery of games stop here, and does
|
|
262
|
+
the game deliver what this promises? Judge locally and send one: the server is
|
|
263
|
+
a gate, not a judge, and agent cover uploads are limited per hour. Record the
|
|
264
|
+
winner — shot name, moment, camera position and target, `fov`, time of day,
|
|
265
|
+
why it won — in `DESIGN.md` when the project keeps one, so a refresh starts
|
|
266
|
+
from it instead of from scratch; a game kept as it is records nothing.
|
|
267
|
+
|
|
268
|
+
## What Genex takes
|
|
269
|
+
|
|
270
|
+
| | |
|
|
271
|
+
| --- | --- |
|
|
272
|
+
| Shape | Landscape 16:9, at least 320×180; shoot 1920×1080 (any 16:9 from 1280×720 up). Anything else is centre-cropped to 16:9. |
|
|
273
|
+
| File | PNG preferred; JPEG and WebP too, recognised by their bytes, not the name. At most 8 MB — over that, a high-quality JPEG. |
|
|
274
|
+
| Stored | 1280×720 WebP plus a JPEG sibling, EXIF-rotated, transparency flattened onto black. A smaller frame is scaled up and goes soft. |
|
|
275
|
+
| Gate | Rec.709 luma of the encoded pixels (0–1) on a 160×90 downscale of the centre 16:9. **Too dark**: mean below 0.12, or more than 85% of samples below 0.10. **Flat**: luma spread (std) below 0.04. A plainly lit scene reads about 0.4–0.6. The gate catches broken frames only; passing it says nothing about beauty. |
|
|
276
|
+
| Who wins | The owner > you > a frame from the owner's own play > a build-session screenshot > the game's menu art > a remix's inherited cover > old AI art — decided by the credential the frame arrives with, never by anything you send. You replace your own pick and every automatic one, never the owner's; their own upload is never gated. |
|
|
277
|
+
| Limits | 10 upload starts and 20 commits an hour per account, for all its agents together. |
|
|
278
|
+
|
|
279
|
+
## Capture and send — lane mechanics
|
|
280
|
+
|
|
281
|
+
Everything above holds in every lane. This section is only how a frame is
|
|
282
|
+
staged, captured and delivered: when the app you run in loads this skill under
|
|
283
|
+
its own preface, with its own capture and cover tools, that preface replaces
|
|
284
|
+
this section wherever they differ.
|
|
285
|
+
|
|
286
|
+
In both Genex lanes `npx genex cover` prints the current cover and who chose
|
|
287
|
+
it, and `npx genex preview` ends with a ➜ line while the game has no cover or
|
|
288
|
+
only a stand-in — your cue, at the next presentable moment rather than mid-fix.
|
|
289
|
+
|
|
290
|
+
### The cover entry
|
|
291
|
+
|
|
292
|
+
The shot runs only on the dev server, behind a URL flag a production build
|
|
293
|
+
cannot contain — Vite replaces `import.meta.env.DEV` with `false` there and
|
|
294
|
+
drops the import:
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
// main.ts — the first statements, ahead of every `await`, so the hook exists once the page loads
|
|
298
|
+
const coverShot = import.meta.env.DEV ? new URLSearchParams(location.search).get("cover") : null;
|
|
299
|
+
let coverWorld: ((game: Game) => void) | undefined;
|
|
300
|
+
if (import.meta.env.DEV && coverShot !== null) {
|
|
301
|
+
const shots = import("./cover-shot.ts");
|
|
302
|
+
const world = new Promise<Game>((resolve) => (coverWorld = resolve));
|
|
303
|
+
let held: Promise<unknown> = world;
|
|
304
|
+
const cover = (name: string) => // one staging at a time, each once the world exists
|
|
305
|
+
(held = held
|
|
306
|
+
.catch(() => {})
|
|
307
|
+
.then(() => Promise.all([shots, world]))
|
|
308
|
+
.then(([m, game]) => m.stageCover(game, name)));
|
|
309
|
+
Object.assign(window, { __cover: cover });
|
|
310
|
+
cover(coverShot); // the URL's own shot, for a tool that can only wait for a selector
|
|
311
|
+
}
|
|
312
|
+
const tier = coverShot !== null ? TIERS.desktop : detectTier(); // a game that picks a tier at boot
|
|
313
|
+
// … build the renderer from `tier` and the world as `game`; a cover boot goes straight to play, HUD hidden …
|
|
314
|
+
coverWorld?.(game);
|
|
315
|
+
// render loop: if (coverShot === null) governor.frame(deltaMs);
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
`stageCover(game, name)` runs the steps of §4 and sets everything absolutely,
|
|
319
|
+
so calling it again re-lands the same frame, or another shot on the same page.
|
|
320
|
+
It resolves the frame's `meter()` numbers once the frame is held, and marks
|
|
321
|
+
`<html data-cover="ready">` (cleared while it stages) for a tool that can only
|
|
322
|
+
wait for a selector. **Every capture goes through `window.__cover('<name>')`**:
|
|
323
|
+
it re-stages the shot it names, queued behind any staging still running, so it
|
|
324
|
+
holds that shot even on a page where you staged another one since. A call that
|
|
325
|
+
does not come back with the numbers — an error, `null` — means the shot is not
|
|
326
|
+
held. After `npm run build`, search `dist/` for one of your shot names — it
|
|
327
|
+
must not be there.
|
|
328
|
+
|
|
329
|
+
### Local agent at a terminal
|
|
330
|
+
|
|
331
|
+
1. **Capture** with whatever browser tool you use for smoke checks, as long as
|
|
332
|
+
it writes a screenshot to a file. Open
|
|
333
|
+
`http://localhost:5173/?genex_local_test=1&cover=<name>` in a 1920×1080
|
|
334
|
+
viewport at device scale 1 (a page of another shape stretches the buffer;
|
|
335
|
+
scale 2 makes a PNG that can pass 8 MB), evaluate `window.__cover('<name>')`
|
|
336
|
+
and wait for its numbers (a selector-only tool waits for
|
|
337
|
+
`html[data-cover="ready"]`, the URL's own shot), and save the viewport
|
|
338
|
+
straight to `.genex/scratch/cover-<name>.png`. Never return the image
|
|
339
|
+
through a JavaScript evaluation — a 1080p frame is megabytes of base64 in
|
|
340
|
+
your context. Reading the canvas instead? Render and read in the same task:
|
|
341
|
+
the WebGL buffer is cleared once a frame is shown.
|
|
342
|
+
2. **Pick:** copy the winner to `.genex/scratch/cover.png`. Only `cover.png`,
|
|
343
|
+
`.jpg`, `.jpeg` or `.webp` there is read, and the newest wins — candidates
|
|
344
|
+
keep other names. To see them at card size, list them in
|
|
345
|
+
`.genex/scratch/contact.html` as `<img width="320">` and screenshot that
|
|
346
|
+
page.
|
|
347
|
+
3. **Send:** the next `npx genex preview` or `npx genex publish` uploads it
|
|
348
|
+
after a successful deploy when its bytes differ from the last frame sent
|
|
349
|
+
(`.genex/cover-upload.json` remembers only that last one; a failed transfer
|
|
350
|
+
is tried again next time). `promote` sends nothing.
|
|
351
|
+
`npx genex cover .genex/scratch/cover.png` sends it now: exit 0 for set or
|
|
352
|
+
outranked, 1 otherwise; `--json` prints one object whose `kind` is
|
|
353
|
+
`applied`, `outranked`, `rejected`, `invalid` or `failed`.
|
|
354
|
+
4. **No browser that can capture the game?** Do not set one up just for this;
|
|
355
|
+
tell the owner they can set a cover on the game's page.
|
|
356
|
+
|
|
357
|
+
### Hosted Genex session
|
|
358
|
+
|
|
359
|
+
`genex_browser` takes the cover itself. One call runs the page load (skipped
|
|
360
|
+
when that URL is already open on unchanged source), a short wait for drawing,
|
|
361
|
+
`actions`, `evaluate` (one expression, at most 4096 characters, 15 s; a promise
|
|
362
|
+
is awaited), then the screenshot you see — and, with `cover: true`, a second,
|
|
363
|
+
lossless PNG of the same 1280×720 viewport, saved as `.genex/scratch/cover.png`
|
|
364
|
+
and sent with `npx genex cover`. Here the capture is that viewport whatever the
|
|
365
|
+
buffer, so stage at 1280×720 (`renderer.setSize(1280, 720, false)`, the
|
|
366
|
+
composer the same): a larger buffer only adds CPU time and memory to the
|
|
367
|
+
sandbox, inside `evaluate`'s 15 s.
|
|
368
|
+
|
|
369
|
+
1. **Judge first, as plain checks, every shot through `__cover`:**
|
|
370
|
+
`{ "url": "http://localhost:5173/?genex_local_test=1&cover=hero", "evaluate": "window.__cover('hero')" }`.
|
|
371
|
+
A heavy world that takes longer than `evaluate`'s 15 s to stage gets
|
|
372
|
+
`"actions": [{ "type": "wait", "ms": 8000 }]` first (up to 10 s each). Read
|
|
373
|
+
each image and the numbers `evaluate` returned; the tool's `frame` measures
|
|
374
|
+
its JPEG of the whole page the same way (`mean`, `darkShare`, and `range`
|
|
375
|
+
for spread). Nominate only a shot whose judging call returned its numbers.
|
|
376
|
+
Switch shots on the same URL with `"evaluate": "window.__cover('vista')"` —
|
|
377
|
+
a different URL means a fresh browser and a full reload, and an idle page
|
|
378
|
+
closes after about 90 s.
|
|
379
|
+
2. **Nominate with the same URL, `"evaluate": "window.__cover('<winner>')"`
|
|
380
|
+
and `"cover": true`** — never by repeating a call that only reads state: a
|
|
381
|
+
reused page still holds the shot you staged last. The capture is the whole
|
|
382
|
+
page, DOM included, and it is taken twice, so the shot must already be held
|
|
383
|
+
— clock stopped, every overlay hidden — when it is taken; a found moment
|
|
384
|
+
needs the HUD hidden and the clock stopped in `evaluate` too.
|
|
385
|
+
3. **Read `cover`:** `submitted` — `npx genex cover` exited 0 and `output` says
|
|
386
|
+
set or outranked (outranked is final); `refused` — `output` says why;
|
|
387
|
+
`not_submitted` — `note` says why, and nothing was sent. A frame is sent only
|
|
388
|
+
when the check's `verification.rendering` is `observed` and the browser did
|
|
389
|
+
not restart mid-check (a restart reloads the game, often to its title). No
|
|
390
|
+
`cover` key at all means this runner cannot nominate: leave it, build
|
|
391
|
+
screenshots stand in.
|
|
392
|
+
4. **When `evaluate` fails.** A timeout skips the capture, so nothing is sent. A
|
|
393
|
+
thrown error does not: the capture goes ahead and nominates whatever is on
|
|
394
|
+
screen. Look at the returned image; if it is not the held shot, fix the shot
|
|
395
|
+
and nominate again — your own pick is yours to replace.
|
|
396
|
+
5. **Mind the two-check budget.** A check with a timeout, a failed `evaluate`
|
|
397
|
+
or an unobserved render counts against the two failures allowed per
|
|
398
|
+
unchanged source — shared with your smoke checks, and blind to the query
|
|
399
|
+
string. Prove the shot on one plain check before nominating, and never spend
|
|
400
|
+
the second failure on a cover: a found frame is a fine cover.
|
|
401
|
+
6. **The sandbox renders on the CPU.** If a frame does not look like the game
|
|
402
|
+
players get (a WebGPU game on a different fallback), do not nominate it, and
|
|
403
|
+
never change working rendering to suit the sandbox.
|
|
404
|
+
|
|
405
|
+
### The answers
|
|
406
|
+
|
|
407
|
+
Each send ends in one of these. The CLI prints the line (in the hosted tool,
|
|
408
|
+
inside `output`):
|
|
409
|
+
|
|
410
|
+
| Answer — the line | What to do |
|
|
411
|
+
| --- | --- |
|
|
412
|
+
| **set** — `Cover set —` | Done until the look changes. Record the shot where the project keeps its design notes. |
|
|
413
|
+
| **outranked** — `Cover unchanged — the owner picked…` | Final, exit 0. Stop: never resend, never ask the owner to clear theirs. |
|
|
414
|
+
| **too dark** — `Cover not used — … too dark…`, then brightness · contrast · near-black | One brighter honest moment of the same game. Dark by design: stop; the owner can set one on the game's page, where their upload is not gated. |
|
|
415
|
+
| **flat** — `… almost one flat colour…` | The canvas had not drawn, a fade or loading screen was up, or sky or fog fills the frame: wait for the render, reframe. |
|
|
416
|
+
| **refused** — `… was refused (unreadable / too_small / too_large)` | The server could not use the file: fix the file, not the game. |
|
|
417
|
+
| **invalid** — not a PNG, JPEG or WebP, over 8 MB, or under 320×180 | Refused before sending: fix the file. |
|
|
418
|
+
| **rate-limited** — `Too many cover uploads…` | Nothing is wrong with the frame. The line names the wait; the next preview sends it again by itself. |
|
|
419
|
+
| **can't send** — sign-in refused, another account, unknown game, or `doesn't take covers from the CLI yet` | `npx genex auth`, or `npx genex link <slug>`; only the owner's account sets a cover; an older stand takes none — stop and say so. |
|
|
@@ -147,11 +147,12 @@ vendored code from memory of another engine.
|
|
|
147
147
|
| stable large-world shadows, cascades, clipmaps, cached updates | `$genex-threejs-shadow-systems` |
|
|
148
148
|
| eye adaptation, tone mapping, output color, LUT grading, and proven static grain | `$genex-threejs-exposure-color-grading` |
|
|
149
149
|
| fixed-view screenshots, input direction, facing, temporal and budget evidence | `$genex-threejs-visual-validation` |
|
|
150
|
+
| **the game's cover** — the one real frame on its gallery card, its page and every shared link: once the game looks like itself and always before its first publish, again when its look changes, or when `npx genex preview` ends asking for one. A real render of the game, never generated art | `$genex-cover` |
|
|
150
151
|
| **a model the player already has** — a `.glb` they exported, bought or made elsewhere: it is IMPORTED, never rebuilt. `npx genex model import <file.glb>` (free) for props and non-biped bodies (then `model rig`/`model animate`), `npx genex character import <file.glb>` for a humanoid that should walk (Uthana auto-rig, then `character animate --locomotion`) | `$genex-ai-model` · `$genex-ai-character` |
|
|
151
152
|
| the default for a concrete object the player looks at up close: a generated GLB for a prop, vehicle, building, or object — from text or a reference image (`--image`); split into named parts (`model segment`); rig + animate any mesh (`model rig` / `model animate`). A space routed to code above does NOT settle these: the ground plan can be code while an object examined up close is generated | `$genex-ai-model` (first time this session: `$genex-lane-card`) |
|
|
152
153
|
| generated surface or terrain texture with real-world UV scale | `$genex-ai-texture` |
|
|
153
154
|
| sky, skybox, horizon, time of day, weather mood, night or space backdrop | build it in code; $genex-threejs-exposure-color-grading owns gameplay lighting and time-of-day readability, with atmosphere techniques chosen for the scene |
|
|
154
|
-
| poster
|
|
155
|
+
| a poster or sign inside the game, sprite, decal, reference sheet, or other 2D art (never the game's own cover) | `$genex-ai-image` |
|
|
155
156
|
| in-world motion art or another requested video | `$genex-ai-video` |
|
|
156
157
|
| sound effect, one looping music bed, or a short spoken line | `$genex-ai-sfx`, `$genex-ai-music`, or `$genex-ai-voice` |
|
|
157
158
|
| requested UI/HUD/menu/interface work, a visible UI problem, or an interface you decided this game wants built with generated art | `$genex-threejs-game-ui` |
|
|
@@ -412,7 +413,9 @@ one smoke pass after the preview, not a new test suite.
|
|
|
412
413
|
Judge evidence against the requested result and current `DESIGN.md`, fix
|
|
413
414
|
meaningful gaps, and move on. An explicit preview or publish request runs the
|
|
414
415
|
existing protected flow directly; report open commitments honestly rather
|
|
415
|
-
than restarting design discovery.
|
|
416
|
+
than restarting design discovery. Before the first publish, the game gets its
|
|
417
|
+
cover — its best real frame, made with `$genex-cover` — unless the owner
|
|
418
|
+
already chose one.
|
|
416
419
|
|
|
417
420
|
## 9. Say it straight
|
|
418
421
|
|
|
@@ -59,6 +59,14 @@ the user in one plain sentence with an offer ("phones will struggle with the
|
|
|
59
59
|
textures — want me to shrink them?"). Fix one only on the user's yes. Never
|
|
60
60
|
turn the report into a milestone before the link.
|
|
61
61
|
|
|
62
|
+
## The cover
|
|
63
|
+
|
|
64
|
+
The game's cover is one real frame of it — what its gallery card, its page and
|
|
65
|
+
every shared link show — and `preview` ends with a line while it has none.
|
|
66
|
+
Once the first preview is up, `$genex-cover` says how to choose, frame and send that
|
|
67
|
+
frame. The game stays as it is: take the frame from play and add no code for
|
|
68
|
+
it, and never set up a browser just for this.
|
|
69
|
+
|
|
62
70
|
## Draft and public version
|
|
63
71
|
|
|
64
72
|
`preview` updates the **draft** and never touches what players are on. The
|