Authoring an Asset-Generation Test Case
An asset-generation test case asks a model
to draw a small pixel sprite with the draw tool (or draw-sheet for a sprite
sheet) — one recorded operation at a time — to match a written brief, rather
than to build a game. There is no target image: the model is given a precise
description and the freedom to draw something that matches it, so the case rewards
creativity rather than the faithful reproduction of a supplied picture. Authoring
one is mostly writing a precise, self-contained brief.
Manifests is the authoritative schema —
every field and the rules enforced at resolution — and you should read it first,
along with the Overview (why the recorded
actions, not the pixels on disk, are the output) and
Evaluation (how the asset is
human-reviewed against the brief, and how cheat-divergence is detected). This
guide is the practical procedure that sits on top of that schema.
Building a playable game instead is a different test type with its own manifest; see Authoring an End-to-End Test Case.
A case draws either a single sprite or a sprite sheet (a set of animation
frames, each its own separate file), chosen by the manifest’s asset_kind field —
a version-level choice, not a variant. The worked examples: the spectra-fighter,
spectra-shard, spectra-flux, and spectra-prism cases are single sprites
(asset_kind = "sprite", the default), drawn with draw; the lanternjaw,
gloamfin, flarefish, and drifter creature cases, the trench-walls tileset,
and the flare-bloom effect case are sprite sheets
(asset_kind = "sprite-sheet"), drawn with draw-sheet --frame <index>, with a
[sheet] table of declared frames and named animation sequences. Read the one
matching the kind you are authoring alongside this guide; a new case should look
like it.
What a case is, and what gets seeded
Section titled “What a case is, and what gets seeded”A version lives under test-cases/<type>/<difficulty>/<slug>/<version>/. Versioning is per-case and
immutable: once a run references a version, that version is frozen. Revise by
adding a new version, never by editing a published one.
test-cases/<type>/<difficulty>/<slug>/<version>/ test-case.toml # manifest: type, canvas, tool, output, sheet, the overall domain variants/ # one standalone TOML file per variant (listed in `variants`) prompt.hbs # rendered per run into the model's instruction (NOT seeded) description.md # site-facing prose (NOT seeded) README.md # human overview (NOT seeded) specs/brief.md # the brief: what to draw + how the tool behaves — SEEDEDA run receives only the seeded files: the selected variant’s brief. There is no
target image — the model draws to match the brief, not to copy a supplied
picture. It also gets the draw (or draw-sheet) binary in its environment, whose
--help is the operations contract; no operations schema is seeded. Everything
marked NOT seeded is authoring- or site-side only.
Procedure
Section titled “Procedure”1. Choose the subject and confirm it qualifies
Section titled “1. Choose the subject and confirm it qualifies”Pick a catalog slug for the lineage (e.g. gloamfin) and the subject to
draw. A good subject reads clearly at the canvas size from silhouette and palette
alone, needs no surrounding game context, and is achievable within the tool’s
operation set. Pick a version (vX.Y.Z).
2. Write the brief
Section titled “2. Write the brief”Write specs/brief.md — a single self-contained file describing:
- what to draw — the subject, its silhouette and orientation, and the framing within the canvas;
- the exact palette — named colors with hex values, stated as the only colors allowed, so a reviewer can judge the asset against the brief unambiguously;
- how the tool behaves — that
drawis the only way to make a mark, that it re-renders the preview after each call, and that the recorded actions are the output (anything drawn outside the tool is discarded).
The same self-containment and precise-values rules as an end-to-end spec apply: the brief must stand on its own, with no link outside the seeded set, and every visual detail written in real terms.
3. Write prompt.hbs
Section titled “3. Write prompt.hbs”A short instruction that points the model at the seeded brief, tells it to read the
binary’s --help for the operations, and states the hard requirements (draw only
through the tool; return when finished). The template renders in strict mode, so
use only the documented variables —
{{variant.slug}}/{{variant.name}}/{{variant.description}} and
{{#each specs}}. A shared quality directive — the brief is the floor, not the
goal; produce the best asset you can within its constraints — is prepended to every
asset-generation prompt automatically at render time, so keep prompt.hbs factual
and do not restate that “aim high” framing yourself.
4. Write the manifest
Section titled “4. Write the manifest”Author test-case.toml per the schema:
-
Metadata —
name,difficulty, andtags, all required and site-facing. -
type = "asset-generation"— required. Omitting it defaults toend-to-end, which then rejects the tables below. -
[canvas]— the fixedwidth,height, andbackgroundthe model draws on. For a sprite sheet this is one frame (each frame is a separate file of this size). Fixing it keeps runs comparable. -
[tool]— thebinary(draw, ordraw-sheetfor a sheet) and thepreviewpath the binary re-renders to after each call (a{frame}template for a sheet). No operations schema — the binary’s--helpis the contract. -
[output]— theactionslog the binary records (a{frame}template for a sheet, one log per frame); this is the authoritative output the reviewed image is regenerated from. -
No references — an asset-generation case declares no
[[reference]]at all. It has no target image; the regenerated asset is reviewed against the brief. Declaring a[[reference]]— common or per-variant — is rejected. -
[sheet](sprite sheets only) — the[[sheet.frame]]entries (each just theindexit is written to) and the named[[sheet.sequence]]animations. -
A
variantslist — an ordered array of paths to standalone variant files undervariants/(the first is the default; at least one is required, usuallybase), each a self-contained TOML document. As a root key it must precede the first table header, and each[[spec]]destdefaults to itssource. To add more, see Creating a Single-Sprite Variant or Creating a Sprite-Sheet Variant, per the case’sasset_kind. -
[[domain]]— the singleoverallscoring domain every asset-generation case declares, and its whole review. There is no[[review_item]]checklist: a produced asset is judged as a whole against its brief, so the reviewer gives one rating and that rating is the run’s (see Judged on one overall rating). The domain is reporter-side and not seeded. Copy it verbatim:[[domain]]id = "overall"name = "Overall"description = "How good the produced asset is overall, judged against the brief."Because the rating is given against the brief alone, anything you would have written as a checklist item belongs in
specs/brief.md.
There is no [build] table and no [[check]] — an asset-generation run
produces a recorded action log, not a static site, and its cheat-divergence signal
is computed by the validator, not by a declared check.
5. Write the non-seeded docs
Section titled “5. Write the non-seeded docs”description.md (site blurb) and README.md (human overview). These never reach
a run; keep them honest about what is seeded.
Validate your work
Section titled “Validate your work”There is no separate authoring linter — you validate a case by resolving and seeding it. For every variant:
tcab prompt --test-case <slug> --version <version> --variant <variant>tcab seed --test-case <slug> --version <version> --variant <variant>prompt renders the instruction (catching strict-mode template errors and
manifest problems); seed writes the seeded repository to disk so you can read
exactly what the model would receive — the brief, plus the seeded
draw.config.json and blank starting frame(s) — and confirm it is self-contained.
Lint the specs and prose with npm run lint:specs (markdownlint + cspell; see
Building).
When the case is ready, exercise it end to end with Run a Test Case. A backend the case is already ingested into keeps serving the old definition until you force a re-ingest, so after editing a case re-ingest it before running — see Running the Local Service Stack.
Next steps
Section titled “Next steps”- Creating a Single-Sprite Variant or
Creating a Sprite-Sheet Variant
(per the case’s
asset_kind) — add a brief variation the model draws toward. - Reviewing Test Run Results — assess a run of your case.