Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Produce a standalone static Texture2D effect or one explicitly timed animated SpriteFrames effect.
.claude/skills/randallliuxin-fx-bundle/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-08 | ✗→✓ | ▲ Improved | -36% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 53% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 187% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 246% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 162% | 0% |
Use this Skill for one detached foreground effect: a projectile, impact, explosion, pickup, muzzle flash, slash arc, aura loop, or dust effect. It delivers either one static Texture2D or one animated SpriteFrames; it never delivers a PackedScene, particle node, trail, shader, sound, light, collision shape, lifecycle script, or a multi-node effect.
Read .godotmaker/asset-runtime/asset-skill-contract.md before accepting the request. For animation rhythm, also read .godotmaker/asset-runtime/animation-planning.md; it supplies planning ranges, not a reason to change an explicit request or reject a valid style.
Validate the shared request with tools/asset_skill_contract_check.py, then validate this family with tools/asset_animated_bundle_contract_check.py --kind request. At final handoff, call the latter with --request <request.json> --result <result.json>. The family checker binds spec.mode to the runtime type and source layout.
The request has asset_type: "fx-bundle" and spec.mode equal to static or animated. References are optional. Pixel-art requests are unsupported in this version: stop clearly rather than quantizing, nearest-neighbour scaling, or labelling ordinary art as pixel art.
Stop only when a required input is unreadable, a declared provider or required reference attachment is objectively unavailable, the request is contradictory, or it asks for an unsupported deliverable such as a particle PackedScene. An image-processing, import, compiler, metadata, path, or validation failure is a production diagnostic: repair it and recheck it before deciding to stop.
This is a standalone Skill. Do not require /gm-asset, tags, stage state, ASSETS.md, generated manifests, or worker registration. A caller may register the returned ready entry separately.
static has no required_actions or actions. It returns one transparentTexture2D at assets/generated/fx-bundle/<asset_id>/<asset_id>.png with a single source layout.
animated has exactly one required action and exactly one action with thesame name. The action has grid.columns, grid.rows, non-empty ordered frame_names, positive fps, explicit boolean loop, and one positive relative duration per frame. The grid contains exactly one cell per frame. It returns one SpriteFrames resource at assets/generated/fx-bundle/<asset_id>/<asset_id>.tres with a grid_sheet source layout.
Never infer timing, frame order, grid, or loop state. Reject duplicates, missing frames, non-positive timing, mismatched durations, or mismatched grid cell count.
.godotmaker/asset-runtime/references/providers/<provider>.md. The runtime installs this guide from the shared gm-asset provider contract. Execute that provider route only; do not silently substitute native, codex, gemini, or openai.
direction, scale, frame count or static target, intended visual style, isolated foreground, solid #FF00FF source background, and no text or UI.
role, and attach the actual image to the chosen provider. A pathname in a text prompt is not an attachment. For Codex, resolve each res:// reference to its actual local readable path and pass those exact paths through referenced_image_paths; for the scripted OpenAI/Gemini routes use asset_source_generate.py reference inputs. If the selected route cannot attach them, stop rather than dropping or replacing the reference.
true, then record the actual generated image path, tool-call ID, coding model/reasoning, image-model identity (or not_exposed_by_subscription_runtime), reference roles, and resolved attachment paths. Claim that image with python .godotmaker/asset-runtime/tools/codex_image_claim.py --plan <plan.json> --report <generated-paths.json> --project-root . --out-report <claim.json>. Never directly copy a Codex image into the project. Missing claim evidence is a STOP.
.godotmaker/asset-generation/traces/<asset_id>.json. It containsasset_id; provider.requested, provider.actual, and, when applicable, provider.referenced_image_paths as the exact absolute local paths passed to the image-provider call; ordered references with the request role, res:// path, sha256, and literal attachment: "referenced_image_paths"; artifacts.raw_sources, provider_claim, process_reports, final_frames, source_layout, and godot_artifact; and ordered steps. source_layout and godot_artifact are objects with exactly type and path: animated FX uses { "type": "grid_sheet", "path": "res://..._sheet.png" } and { "type": "SpriteFrames", "path": "res://....tres" }; static FX uses { "type": "single", "path": "res://....png" } and { "type": "Texture2D", "path": "res://....png" }. Every artifact path is a contained res:// or project-relative path. Each step records reason, command_or_code, inputs, outputs, modified_files, diagnostic, and repair. Project tools are preferred, but a temporary image tool or diagnostic script is allowed when this trace is truthful; its name alone is never a failure. When a temporary script is created, list that script's exact path in the same step's modified_files as well as the generated assets it changes; do not omit the script merely because it is an implementation detail.
References influence scale, direction, palette, and visual style. Do not claim they were attached or validated unless the provider trace proves it.
Work in the following loop until every applicable L0-L4 check passes or a real STOP condition occurs. Never mark the first failed check as the final result.
#FF00FF background before deterministic cleanup, with no text or UI.
reports, source layout, final artifact, and Godot artifact in the trace.
standalone_validation.compile_and_validate() for the applicable L0-L4 checks. Read the diagnostic, then repair source art, processing parameters, metadata, paths, or Godot artifact and rerun the checks.
validation.passed: true,write the final result, and run the request/result handoff checker. Preserve the build fingerprint as evidence; /gm-asset validates the result and records it directly in ASSETS.md. Then write that generic result object to ASSET_RESULT.json in the project root and return only its JSON contents: no Markdown links, prose, or alternate result shape. L5/L6 visual judgment belongs to the private Eval, not this production Skill.
L3 is a real Godot import/load probe, not a PATH-presence check. When GM_EVAL_GODOT_PATH is set, it is the pinned executable for this run: pass that exact value to compile_and_validate(..., godot_path=...) (or leave its historical "godot" placeholder for the shared validator to resolve). Do not replace it with a bare godot, discover another installation, or mark L3 as passed without invoking it. Outside an Eval, resolve the configured executable with python tools/agent_runtime.py godot_path; if it is genuinely absent or unrunnable, record the diagnostic and STOP only after the production repair options are exhausted.
Use tools/asset_sheet_process.py --snap-mode autoslice only when every disconnected foreground component is itself one logical effect. Do not supply --grid to autoslice. Follow it with curation and tools/asset_curation_select.py; selection invokes asset_image_finalize.py for transparent cleanup, aspect-preserving scaling, centering, and padding before the stable PNG is published.
If disconnected sparks, fragments, glow, or dust semantically form one effect, preserve the whole composition instead. Use an explicit one-cell/grid curation route or finalize the full source deterministically; do not let autoslice split one effect into unrelated runtime assets. If autoslice --names does not match the detected regions it returns needs_regeneration without partial output. Treat that as a repair diagnostic: regenerate or relayout the source, or correct the intended naming; never drop regions or silently assemble a different effect.
After selecting one candidate at the final PNG path, compile and validate its Texture2D output through the shared route. Preserve the reports and fingerprint as result evidence; do not create a registration record.
Use tools/asset_action_process.py with --kind fx, the declared explicit grid, ordered frame names, action name, FPS, loop flag, durations, magenta cleanup, and --align center. Preserve raw sheet, processed transparent frames, delivery sheet, GIF preview, processing report, and action metadata. Animation never uses autoslice or an atlas assembler. Publish each processed frame at assets/generated/fx-bundle/<asset_id>/<asset_id>_<action>_<frame>.png; this is the canonical frame path consumed by the L0-L4 SpriteFrames validation route. Pass --final-dir assets/generated/fx-bundle/<asset_id> and --final-prefix <asset_id>_<action> and --final-sheet-name <asset_id>_sheet.png to the action processor. Do not use only <asset_id> as the final prefix: each declared frame_name already carries its own ordered frame label, so omitting the action prefix changes the stable runtime path. The separate final sheet name preserves the one stable source-layout path consumed by the SpriteFrames compiler.
Use grid.columns * grid.rows, ordered frame_names, frame_durations, and loop as the only frame-slicing facts. Do not split, merge, or reorder frames from components, bounds, or autoslice regions.
On status: "needs_regeneration", preserve the report, repair or regenerate the same source with the declared grid, and process it again. If visual grid rejections remain after suitable provider repair, process the preserved source again with the same grid, names, timing, delivery paths, and --fixed-grid-fallback. Do not run connected-component recovery. Preserve the action report's structured warnings[], complete compilation and L0-L4, and copy a concise warning summary to the final result's string validation.notes.
Compile and validate the one SpriteFrames artifact through the shared route. Preserve frame order, grid, timing, loop state, alignment, paths, and fingerprint as result evidence.
An animated result has one SpriteFrames runtime output and one stable grid_sheet source. A static result has one Texture2D runtime output at the same stable PNG path as its single source. Both final results include explicit passing L0 through L4 evidence; no other runtime Godot type is valid. ASSET_RESULT.json is the final machine-readable handoff, not a report link or a summary of another JSON file.
Before writing ASSET_RESULT.json, reread the emitted trace and validate its own paths against the files on disk. source_layout and godot_artifact live inside trace.artifacts, never at the trace root. For an animation, trace.artifacts.final_frames is the exact ordered list from the action processor's recorded final-frame paths; do not reconstruct or edit these names by string concatenation. Reject and repair the trace if a listed frame is missing, the count differs from the request, a field is outside artifacts, or the layout/artifact type and path do not match the final result.
json{ "artifacts": { "source_layout": { "type": "grid_sheet", "path": "res://assets/generated/fx-bundle/<asset_id>/<asset_id>_sheet.png" }, "godot_artifact": { "type": "SpriteFrames", "path": "res://assets/generated/fx-bundle/<asset_id>/<asset_id>.tres" } } }
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 20,399 | 6,482 | -68% | 1 | 1 | 0% | 4,552 | 3,452 | -24% | 0 | 0 | — |
case-02 | fail→fail | 13,458 | 5,486 | -59% | 1 | 1 | 0% | 825 | 3,427 | +315% | 0 | 0 | — |
case-03 | fail→fail | 24,782 | 6,836 | -72% | 1 | 1 | 0% | 5,435 | 3,639 | -33% | 0 | 0 | — |
case-04 | fail→fail | 25,438 | 5,488 | -78% | 1 | 1 | 0% | 5,230 | 3,347 | -36% | 0 | 0 | — |
case-05 | fail→fail | 14,187 | 6,372 | -55% | 1 | 1 | 0% | 2,838 | 3,430 | +21% | 0 | 0 | — |
case-06 | fail→fail | 29,500 | 7,205 | -76% | 1 | 1 | 0% | 6,192 | 3,440 | -44% | 0 | 0 | — |
case-07 | fail→fail | 12,500 | 6,911 | -45% | 1 | 1 | 0% | 1,999 | 4,436 | +122% | 0 | 0 | — |
case-08 | fail→pass | 33,326 | 5,076 | -85% | 1 | 1 | 0% | 6,197 | 3,946 | -36% | 0 | 0 | — |
case-09 | fail→fail | 19,102 | 8,004 | -58% | 1 | 1 | 0% | 3,732 | 3,597 | -4% | 0 | 0 | — |
case-10 | fail→pass | 15,028 | 8,082 | -46% | 1 | 1 | 0% | 2,941 | 4,504 | +53% | 0 | 0 | — |
case-11 | fail→pass | 8,524 | 5,113 | -40% | 1 | 1 | 0% | 1,459 | 4,187 | +187% | 0 | 0 | — |
case-12 | fail→pass | 6,635 | 3,468 | -48% | 1 | 1 | 0% | 1,103 | 3,816 | +246% | 0 | 0 | — |
case-13 | fail→pass | 9,590 | 5,046 | -47% | 1 | 1 | 0% | 1,508 | 3,948 | +162% | 0 | 0 | — |
case-14 | fail→fail | 7,424 | 4,948 | -33% | 1 | 1 | 0% | 1,241 | 3,247 | +162% | 0 | 0 | — |
case-15 | fail→pass | 8,817 | 4,077 | -54% | 1 | 1 | 0% | 1,715 | 3,778 | +120% | 0 | 0 | — |
case-16 | fail→pass | 8,264 | 4,337 | -48% | 1 | 1 | 0% | 1,459 | 3,929 | +169% | 0 | 0 | — |
case-17 | fail→fail | 15,927 | 2,087 | -87% | 1 | 1 | 0% | 3,186 | 3,392 | +6% | 0 | 0 | — |
case-18 | fail→pass | 9,244 | 4,029 | -56% | 1 | 1 | 0% | 1,789 | 3,863 | +116% | 0 | 0 | — |
case-19 | pass→pass | 9,040 | 3,724 | -59% | 1 | 1 | 0% | 1,488 | 3,783 | +154% | 0 | 0 | — |
case-20 | pass→pass | 10,091 | 2,775 | -73% | 1 | 1 | 0% | 1,781 | 3,559 | +100% | 0 | 0 | — |
case-21 | fail→pass | 28,672 | 9,058 | -68% | 1 | 1 | 0% | 6,171 | 4,745 | -23% | 0 | 0 | — |
case-22 | pass→pass | 10,315 | 5,762 | -44% | 1 | 1 | 0% | 1,824 | 4,134 | +127% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 14 counted toward the lift figure. The other 8 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +41 percentage points is the difference between those two pass rates over the 14 comparable cases. 3 cases got worse with the skill loaded, and they are included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.