@genex-ai/cli-demo 1.11.1-dev.539 → 1.11.3-dev.541
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/dist/index.js +78 -6
- package/package.json +1 -1
- package/templates/skills/genex-ai-video/SKILL.md +34 -4
- package/templates/skills/genex-game-director/SKILL.md +4 -0
- package/templates/skills/genex-game-director/references/routing-map.md +3 -0
- package/templates/skills/genex-tool-video/SKILL.md +17 -1
package/dist/index.js
CHANGED
|
@@ -972,6 +972,7 @@ Important note: put soul into your creations, with many details and love. Aim to
|
|
|
972
972
|
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.
|
|
973
973
|
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.
|
|
974
974
|
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.
|
|
975
|
+
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.
|
|
975
976
|
${CONTRACT_END}
|
|
976
977
|
`;
|
|
977
978
|
var GENEX_TOOLS_CONTRACT_BLOCK = `${CONTRACT_BEGIN}
|
|
@@ -6160,7 +6161,8 @@ async function detectSurfaceScan(cwd = process.cwd()) {
|
|
|
6160
6161
|
squarePoints: [],
|
|
6161
6162
|
depthRange: [],
|
|
6162
6163
|
mediaElementAudio: [],
|
|
6163
|
-
deferredAudioContext: []
|
|
6164
|
+
deferredAudioContext: [],
|
|
6165
|
+
usesThree: false
|
|
6164
6166
|
};
|
|
6165
6167
|
const srcDir = path17.join(cwd, "src");
|
|
6166
6168
|
let entries;
|
|
@@ -6208,6 +6210,7 @@ async function detectSurfaceScan(cwd = process.cwd()) {
|
|
|
6208
6210
|
ratio
|
|
6209
6211
|
});
|
|
6210
6212
|
}
|
|
6213
|
+
if (/\bfrom\s*["']three(?:\/[^"']*)?["']/.test(content)) found.usesThree = true;
|
|
6211
6214
|
const threeAudioImport = /import\s+(?:type\s+)?\{[^}]*\bAudio\b[^}]*\}\s+from\s*["']three["']/.test(
|
|
6212
6215
|
content
|
|
6213
6216
|
);
|
|
@@ -6376,8 +6379,9 @@ function surfaceNudges(log, s) {
|
|
|
6376
6379
|
}
|
|
6377
6380
|
if (s.mediaElementAudio.length) {
|
|
6378
6381
|
const list = s.mediaElementAudio.map((d) => `${d.where} \u2014 ${d.detail}`).join("; ");
|
|
6382
|
+
const fix = s.usesThree ? `THREE.Audio/PositionalAudio on one AudioListener have none of this \u2014 genex-ai-sfx ships the pooled one-shot, the live-value loop, and the decode-during-the-menu preload.` : `Plain WebAudio has none of this \u2014 one AudioContext (created inside the first user gesture), fetch + decodeAudioData during the menu, an AudioBufferSourceNode per one-shot, and a GainNode per live value. A music bed that only plays/pauses MAY stay an <audio> element; anything whose volume or rate tracks gameplay must not.`;
|
|
6379
6383
|
log.warn(
|
|
6380
|
-
`HTML <audio> elements are carrying this game's sound: ${list}. On iPhone an <audio> element is a handle on the operating system's media pipeline in ANOTHER PROCESS: every write to .volume or .playbackRate is a cross-process call, and play() is slow and asynchronous. A sound driven from a live value \u2014 wheels from speed, engine from RPM \u2014 writes 60-120 of those a second and stutters the whole game, while one-shots arrive late. It disguises itself as a graphics problem perfectly: only while moving, identical at every quality setting, desktop fine.
|
|
6384
|
+
`HTML <audio> elements are carrying this game's sound: ${list}. On iPhone an <audio> element is a handle on the operating system's media pipeline in ANOTHER PROCESS: every write to .volume or .playbackRate is a cross-process call, and play() is slow and asynchronous. A sound driven from a live value \u2014 wheels from speed, engine from RPM \u2014 writes 60-120 of those a second and stutters the whole game, while one-shots arrive late. It disguises itself as a graphics problem perfectly: only while moving, identical at every quality setting, desktop fine. ${fix}`
|
|
6381
6385
|
);
|
|
6382
6386
|
}
|
|
6383
6387
|
if (s.deferredAudioContext.length) {
|
|
@@ -7405,6 +7409,20 @@ async function runGenerate(kind, opts) {
|
|
|
7405
7409
|
}
|
|
7406
7410
|
opts = { ...opts, frameUrl: inlined.dataUri };
|
|
7407
7411
|
}
|
|
7412
|
+
for (const [field, flag] of [
|
|
7413
|
+
["firstFrameUrl", "--start-frame/--first-frame"],
|
|
7414
|
+
["lastFrameUrl", "--last-frame"]
|
|
7415
|
+
]) {
|
|
7416
|
+
const ref = opts[field];
|
|
7417
|
+
if (kind !== "video" || !ref || isRemoteRef(ref)) continue;
|
|
7418
|
+
const inlined = await inlineLocalImage(ref, flag);
|
|
7419
|
+
if (!inlined.ok) {
|
|
7420
|
+
log.error(inlined.error);
|
|
7421
|
+
process.exitCode = 1;
|
|
7422
|
+
return;
|
|
7423
|
+
}
|
|
7424
|
+
opts = { ...opts, [field]: inlined.dataUri };
|
|
7425
|
+
}
|
|
7408
7426
|
if (kind === "video" && opts.refs?.length) {
|
|
7409
7427
|
const refs = [];
|
|
7410
7428
|
for (const ref of opts.refs) {
|
|
@@ -21886,8 +21904,13 @@ ${c.bold("Options for the generators (`model` `sfx` `music` `voice` `texture` `i
|
|
|
21886
21904
|
it, model default).
|
|
21887
21905
|
--frame <url|file> (video) animate from THIS frame back to itself (seamless
|
|
21888
21906
|
loop) \u2014 an asset URL or a local image file (\u22644 MB).
|
|
21889
|
-
--
|
|
21890
|
-
|
|
21907
|
+
--start-frame <url|file> (video) continue from this exact frame, no end
|
|
21908
|
+
anchor \u2014 the clip-chaining primitive: extract the last
|
|
21909
|
+
frame of the previous clip (ffmpeg) and pass it here.
|
|
21910
|
+
Anchors are compositional guidance, not pixel-pinning;
|
|
21911
|
+
chain from REAL extracted frames so drift can't stack.
|
|
21912
|
+
--first-frame <url|file> (video) start frame; alone it means --start-frame \u2026
|
|
21913
|
+
--last-frame <url|file> (video) \u2026 add this to also anchor the end frame.
|
|
21891
21914
|
--ref <url|file> (video, repeatable \xD79) subject/style reference images \u2014
|
|
21892
21915
|
cite them in the prompt as "Image 1"\u2026"Image N"; keeps
|
|
21893
21916
|
the same character/style across many clips. Cannot be
|
|
@@ -22086,7 +22109,8 @@ ${c.bold("Generate")} typ
|
|
|
22086
22109
|
--transparent \u2026with a real alpha channel (sprites, icons, logos).
|
|
22087
22110
|
--edit <path|url> \u2026edit an existing image with the prompt.
|
|
22088
22111
|
--remove-bg / --bg-mode <m> \u2026cut the background (sprite|glyph|sheet|matte).
|
|
22089
|
-
genex video "<prompt>" A video (mp4). --loop, --frame <img
|
|
22112
|
+
genex video "<prompt>" A video (mp4). --loop, --frame <img>, ${cr("video")}
|
|
22113
|
+
--start-frame <img> (continue a clip).
|
|
22090
22114
|
genex texture "<prompt>" A tiling PBR texture set. --terrain. ${cr("texture")}
|
|
22091
22115
|
genex sfx "<prompt>" A sound effect (mp3). --duration. ${cr("sfx")}
|
|
22092
22116
|
genex music "<prompt>" A looping instrumental track (mp3). ${cr("music")}
|
|
@@ -22146,6 +22170,51 @@ ${c.bold("Examples")}
|
|
|
22146
22170
|
Hosting, publishing, multiplayer, remixing and custom domains are the Genex
|
|
22147
22171
|
platform \u2014 build a game there from one prompt: ${c.cyan("https://genex.games")}
|
|
22148
22172
|
`;
|
|
22173
|
+
var COMMAND_HELP = {
|
|
22174
|
+
video: `${c.bold("genex video")} \u2014 generate a video clip (mp4, MiniMax H3 Max \u2014 the flagship; plain H3 for seamless loops and 2k/4k; native stereo audio on every non-loop clip).
|
|
22175
|
+
|
|
22176
|
+
${c.bold("Modes")}
|
|
22177
|
+
genex video "<prompt>" text-to-video (16:9).
|
|
22178
|
+
genex video "<prompt>" --start-frame <img> continue from this frame \u2014 the
|
|
22179
|
+
clip-chaining primitive.
|
|
22180
|
+
genex video "<prompt>" --frame <img> animate from the frame back to
|
|
22181
|
+
itself (seamless loop; menus).
|
|
22182
|
+
genex video "<prompt>" --first-frame <img> --last-frame <img>
|
|
22183
|
+
two-frame motion (both anchored).
|
|
22184
|
+
genex video "<prompt>" --ref <img> [--ref \u2026\xD79] same subject/style across many
|
|
22185
|
+
clips ("Image 1"\u2026"Image N").
|
|
22186
|
+
genex video "<prompt>" --loop prompt-only seamless loop (no
|
|
22187
|
+
conditioning frame; Luma Ray-2).
|
|
22188
|
+
|
|
22189
|
+
${c.bold("Flags")}
|
|
22190
|
+
--start-frame <url|file> continue-from anchor; local files inline (\u22644 MB).
|
|
22191
|
+
--frame / --first-frame / --last-frame <url|file> ditto.
|
|
22192
|
+
--ref <url|file> repeatable \xD79; not combinable with frames/--loop.
|
|
22193
|
+
--duration <s> 5-15 (integer seconds; H3's own band). Default 5,
|
|
22194
|
+
loops/pairs 8. Longer scenes: chain clips.
|
|
22195
|
+
--resolution <r> 480p | 768p (default, top native) | 2k | 4k.
|
|
22196
|
+
--no-wait enqueue only; attach later with genex wait <id>.
|
|
22197
|
+
|
|
22198
|
+
Aspect: text/ref clips are 16:9. Frame-conditioned clips FOLLOW THE SOURCE
|
|
22199
|
+
IMAGE \u2014 a square image (genex image --aspect square) yields a square video.
|
|
22200
|
+
|
|
22201
|
+
${c.bold("Chaining clips (playable films, cutscene sequences)")}
|
|
22202
|
+
Frame anchors are COMPOSITIONAL GUIDANCE, not pixel-pinning \u2014 the model
|
|
22203
|
+
repaints the frame (measured ~21 dB vs the supplied image; identical would be
|
|
22204
|
+
~35-40 dB). Chains still hold if every clip starts from the PREVIOUS CLIP'S
|
|
22205
|
+
REAL last frame, because drift never accumulates:
|
|
22206
|
+
ffmpeg -sseof -0.2 -i prev.mp4 -update 1 -q:v 1 last.png
|
|
22207
|
+
genex video "<what changes next>" --start-frame last.png
|
|
22208
|
+
Cut clip-to-clip (or crossfade ~200 ms to hide the residual repaint). Keep
|
|
22209
|
+
in-game <video> muted by default \u2014 every H3 clip carries audio.
|
|
22210
|
+
|
|
22211
|
+
${c.bold("Content filter")}
|
|
22212
|
+
The provider rejects anatomy-invasion phrasing (cables/wires/needles entering
|
|
22213
|
+
a body) as body horror \u2014 describe the object or machine instead: "a
|
|
22214
|
+
statue-like figure threaded into the wall" passes where "cables entering her
|
|
22215
|
+
spine" fails. Rejections are never retryable; reword and re-run.
|
|
22216
|
+
`
|
|
22217
|
+
};
|
|
22149
22218
|
function parseArgs(argv) {
|
|
22150
22219
|
const parsed = {
|
|
22151
22220
|
command: void 0,
|
|
@@ -22183,6 +22252,7 @@ function parseArgs(argv) {
|
|
|
22183
22252
|
"--voice",
|
|
22184
22253
|
"--voice-id",
|
|
22185
22254
|
"--frame",
|
|
22255
|
+
"--start-frame",
|
|
22186
22256
|
"--first-frame",
|
|
22187
22257
|
"--last-frame",
|
|
22188
22258
|
"--ref",
|
|
@@ -22716,6 +22786,7 @@ function applyValueFlag(options, flag, value) {
|
|
|
22716
22786
|
case "--video":
|
|
22717
22787
|
options.video = value;
|
|
22718
22788
|
break;
|
|
22789
|
+
case "--start-frame":
|
|
22719
22790
|
case "--first-frame":
|
|
22720
22791
|
options.firstFrameUrl = value;
|
|
22721
22792
|
break;
|
|
@@ -22777,7 +22848,8 @@ async function main() {
|
|
|
22777
22848
|
const mode = await workspaceMode();
|
|
22778
22849
|
setWorkspaceHeader(mode === "tools" ? "tools" : null);
|
|
22779
22850
|
if (parsed.help || parsed.command === void 0) {
|
|
22780
|
-
|
|
22851
|
+
const perCommand = parsed.command === void 0 ? void 0 : COMMAND_HELP[parsed.command];
|
|
22852
|
+
log.plain(perCommand ?? (mode === "tools" ? HELP_TOOLS : HELP));
|
|
22781
22853
|
return;
|
|
22782
22854
|
}
|
|
22783
22855
|
const isBlenderMcp = parsed.command === "blender" && parsed.options.name === "mcp";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genex-ai/cli-demo",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.3-dev.541",
|
|
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": {
|
|
@@ -146,8 +146,19 @@ See `$genex-threejs-multiplayer` for the `shared` channel rules and the room API
|
|
|
146
146
|
- `--frame <url|file>` — one generated image (or a local file ≤4 MB) as BOTH
|
|
147
147
|
first and last frame — the seamless-loop mode (motion must return to its
|
|
148
148
|
start; the seam is mathematically exact).
|
|
149
|
-
- `--
|
|
150
|
-
|
|
149
|
+
- `--start-frame <url|file>` — continue from this frame, no end anchor — the
|
|
150
|
+
clip-chaining primitive (see below). Local files inline like `--frame`.
|
|
151
|
+
- `--first-frame <url|file>` / `--last-frame <url|file>` — two-frame motion
|
|
152
|
+
between two stills (a genuine state change — a door opens, day turns to
|
|
153
|
+
night). `--first-frame` alone means `--start-frame`.
|
|
154
|
+
|
|
155
|
+
**Frame anchors are compositional guidance, not pixel-pinning.** The model
|
|
156
|
+
repaints every anchor — the clip's first frame lands near the supplied image
|
|
157
|
+
(same scene, same composition) but not ON it, and regenerating doesn't change
|
|
158
|
+
that; it is how the mode works. Plan for it: chains stay coherent when each
|
|
159
|
+
clip starts from the previous clip's REAL frame (below), and a supplied
|
|
160
|
+
`--last-frame` steers where motion ends rather than guaranteeing the exact
|
|
161
|
+
pixels.
|
|
151
162
|
- `--ref <url|file>` — repeatable, up to 9 subject/style reference images.
|
|
152
163
|
Cite each in the prompt by its order: "Image 1 is the hero — she walks into
|
|
153
164
|
frame…". This is how the SAME character or art style holds across many clips
|
|
@@ -168,8 +179,21 @@ evidence detective game, a video-book. The pattern that makes it hold together:
|
|
|
168
179
|
- **Branching scenes**: generate one clip per story node at build time, ship
|
|
169
180
|
the mp4 URLs in a scene-graph JSON, play them full-screen with DOM choice
|
|
170
181
|
buttons; preload the clips reachable from the current node while it plays.
|
|
171
|
-
- **Visual continuity
|
|
172
|
-
|
|
182
|
+
- **Visual continuity — chain from REAL frames**: extract the previous clip's
|
|
183
|
+
actual last frame and seed the next clip with it:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
ffmpeg -sseof -0.2 -i prev.mp4 -update 1 -q:v 1 last.png
|
|
187
|
+
npx genex video "she turns and walks toward the far door" --start-frame last.png
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Never chain from the image you WISHED the clip ended on — anchors are
|
|
191
|
+
repainted (above), so the wish and the clip disagree and every join jumps.
|
|
192
|
+
Chaining from the real frame keeps drift from accumulating; the residual
|
|
193
|
+
repaint at each cut is small, and a ~200 ms crossfade between the two
|
|
194
|
+
`<video>` elements hides it entirely. Write chained prompts as CHANGE ONLY
|
|
195
|
+
("she turns…", "the light flickers out") — the start frame already says
|
|
196
|
+
everything else.
|
|
173
197
|
- **Cast consistency**: give every scene the same `--ref` images of your
|
|
174
198
|
protagonist and key locations — the single biggest quality lever for any
|
|
175
199
|
multi-clip story.
|
|
@@ -181,6 +205,12 @@ evidence detective game, a video-book. The pattern that makes it hold together:
|
|
|
181
205
|
- **"Not authorized"** — run `npx @genex-ai/cli-demo@dev init` first (it writes your `GENEX_TOKEN`).
|
|
182
206
|
- **"Prompt rejected"** — the provider's content-safety filter blocked the prompt.
|
|
183
207
|
This is non-retryable; retrying the same wording fails again. Rewrite the prompt.
|
|
208
|
+
The measured false-positive class is anatomy being pierced or entered
|
|
209
|
+
(cables/wires/needles into a body — biomech and cyberpunk vocabulary trips
|
|
210
|
+
it). Describe the object or machine instead of the anatomy: "a statue-like
|
|
211
|
+
figure threaded into the wall" passes where "cables entering her spine"
|
|
212
|
+
fails. Word it that way on the FIRST try — each rejection still ends a
|
|
213
|
+
billed-then-refunded round trip.
|
|
184
214
|
- **Nothing plays / black surface** — the first `video.play()` must run inside a user
|
|
185
215
|
gesture (click/keydown); confirm it's called and its promise rejection is logged.
|
|
186
216
|
- **Tainted-source / security error** — set `video.crossOrigin = "anonymous"` before
|
|
@@ -54,6 +54,10 @@ Use the request in front of you, not the oldest description of the project.
|
|
|
54
54
|
invent or propose game concepts for them.
|
|
55
55
|
- **Existing project** respects its renderer, physics, file conventions, and
|
|
56
56
|
working systems unless the player asks to change them.
|
|
57
|
+
- **A tagged reference** (source under `.genex/refs/<slug>/`) owns the
|
|
58
|
+
subsystem it was tagged for: read its `_map.md` and implementing files
|
|
59
|
+
before choosing a lane — it outranks the default lane, including the
|
|
60
|
+
vendored controllers, for that subsystem.
|
|
57
61
|
|
|
58
62
|
Ask one decision at a time. Never ask the player to choose an SDK, engine,
|
|
59
63
|
renderer, file layout, provider, or other implementation detail. Product
|
|
@@ -28,6 +28,9 @@ copy demo architecture.
|
|
|
28
28
|
3D,” ask one plain question: normal generated GLB, or editable parameterized
|
|
29
29
|
Three.js code? Explicit `GLB`, `procedural`, `parametric`, `code-built`, or
|
|
30
30
|
`variations` language chooses directly.
|
|
31
|
+
- **Tagged reference:** source under `.genex/refs/<slug>/` owns the subsystem
|
|
32
|
+
it was tagged for — read its `_map.md` and implementing files before choosing
|
|
33
|
+
a lane; it outranks the default lane, vendored controllers included.
|
|
31
34
|
|
|
32
35
|
## Route by system
|
|
33
36
|
|
|
@@ -33,7 +33,22 @@ npx genex video "camera drifts slowly forward, banners stirring" --frame ./asset
|
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
- `--frame <path|url>` — animate FROM this frame back to itself, i.e. a seamless loop. Local file (≤ 4 MB) or a previous generation's URL.
|
|
36
|
-
- `--
|
|
36
|
+
- `--start-frame <path|url>` — continue from this frame, no end anchor — the clip-chaining primitive.
|
|
37
|
+
- `--first-frame <path|url>` / `--last-frame <path|url>` — a two-frame motion between them. All frame anchors take local files.
|
|
38
|
+
|
|
39
|
+
Frame anchors are **compositional guidance, not pixel-pinning** — the model
|
|
40
|
+
repaints the frame (same scene and composition, not the same pixels), and
|
|
41
|
+
regenerating doesn't change that. Chained clips (a cutscene sequence, a
|
|
42
|
+
branching video story) stay coherent when each clip starts from the previous
|
|
43
|
+
clip's REAL last frame, so drift never accumulates:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
ffmpeg -sseof -0.2 -i ./assets/prev.mp4 -update 1 -q:v 1 last.png
|
|
47
|
+
npx genex video "she turns and walks toward the far door" --start-frame last.png
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Write chained prompts as CHANGE ONLY — the start frame already says everything
|
|
51
|
+
else. Cut clip-to-clip, or crossfade ~200 ms to hide the residual repaint.
|
|
37
52
|
|
|
38
53
|
## Options
|
|
39
54
|
|
|
@@ -61,5 +76,6 @@ command bills a NEW clip** — it is never a way to check on one already running
|
|
|
61
76
|
## Troubleshooting
|
|
62
77
|
|
|
63
78
|
- **It failed** — video fails server-side more often than any other lane, and every attempt is minutes. The CLI counts failures in this folder and tells you when to stop: after the second, use a still image instead and say so in one plain line. A third attempt bills the same and returns the same.
|
|
79
|
+
- **"Prompt rejected"** — the content-safety filter; never retryable with the same wording. The measured false-positive class is anatomy being pierced or entered (cables/wires/needles into a body — biomech vocabulary trips it). Describe the object or machine instead: "a statue-like figure threaded into the wall" passes where "cables entering her spine" fails.
|
|
64
80
|
- **Out of credits** — the error prints balance, price and refill date. Relay it; don't retry.
|
|
65
81
|
- **Anything else** — `npx genex doctor` reports sign-in, credits, and whether the video lane is live.
|