Skip to content

Authoring a Full-Stack Test Case

A full-stack test case is a playable game a model builds from a self-contained spec, and whose assets the model must also produce during the run using the asset-generation binaries on the run image’s PATH. Authoring one is the end-to-end procedure plus an asset-production contract. This guide covers what full-stack adds; read the end-to-end guide first for the shared work, and Full-Stack Tests for the authoritative schema.

The editorial rules for the seeded specs and the prompt apply unchanged; see Writing Case Specifications and Prompts.

The worked example is the Hollowdeep case (test-cases/full-stack/medium/hollowdeep/v1.0.0/), a sealed-colony survival sim whose model draws every sprite, authors every particle overlay, and synthesizes every sound it plays.

The choice between the three types is about where the art comes from.

  • To measure software development alone, pre-provide the art and author an end-to-end case. Fixed seeded assets keep runs comparable.
  • To measure asset creation alone, author an asset-generation case.
  • To measure whether one model can carry a whole small product, covering art direction, effects, audio, and code, author a full-stack case.

A full-stack run executes in one of two run images, picked by the case’s asset_dimension. Both are the Rust and wasm base image plus asset-generation binaries on PATH.

asset_dimension = "2d", the default, carries the six 2D binaries.

BinaryProducesConsumed as
drawa single sprite → PNGa PNG the game draws
draw-sheeta sprite sheet → per-frame PNGsframes the game animates
particle-2da particle system → system.jsonplayed live via @clockwyrks/particle-runtime’s ./canvas binding
sfx-syntha procedural sound effect → .wavplayed via Web Audio
sfx-samplea sampled effect over a declared sample pack → .wavplayed via Web Audio
musicsequenced music over a declared instrument bank → .wav + .midplayed via Web Audio

asset_dimension = "3d" carries those six and three more.

BinaryProducesConsumed as
voxela static voxel model → mesh.glbdecoded by @clockwyrks/voxel-runtime’s parseGlb
voxel-anima rigged, animated model → per-part .glb + rig.jsonposed and drawn via the voxel runtime’s ./three binding
particle-3da volumetric particle system → system.jsonplayed live via @clockwyrks/particle-runtime’s ./three binding

Each binary’s --help is its contract, and the asset-generation binary pages are the authoritative reference for what each one does. Pick the dimension the concept’s art asks for and declare it in the manifest, since it fixes the tooling for every variant of the version.

The produced files are build inputs rather than separately-scored artifacts. The model produces them once, commits them, and the build consumes them exactly as an end-to-end build consumes seeded art. They are judged as part of the running program a reviewer plays.

Follow the end-to-end procedure. The steps below replace or add to it; everything not mentioned is unchanged.

1. Confirm it qualifies, and pin the difficulty

Section titled “1. Confirm it qualifies, and pin the difficulty”

Every end-to-end design requirement still holds. Two additions:

  • The game’s art must be producible with the binaries of the dimension the case declares: the six 2D tools, or those plus voxel, voxel-anim, and particle-3d. A concept whose art needs meshed or SDF geometry, ui screens, or material textures belongs to another type.
  • The model builds the game and produces a full asset set, so a full-stack case is heavier than the same game as end-to-end. Set difficulty and max_runtime_hours accordingly; Hollowdeep is medium with eight hours.

2–5. Foundations, spec decomposition, prompt, reference implementations

Section titled “2–5. Foundations, spec decomposition, prompt, reference implementations”

Unchanged from end-to-end, with two notes.

  • The asset-quality directive stays out of the prompt. The harness prepends the standing quality directive at render time, which tells the model to author real assets with the binaries the case’s asset_dimension puts on PATH and keep the build self-contained. Cover only case-specific detail in prompt.hbs.
  • A new case declares no reference views. The visual bar is stated in the specs, and the reviewer judges the produced build against them.

6. Write specs/assets.md, the asset-production contract

Section titled “6. Write specs/assets.md, the asset-production contract”

This seeded spec tells the model what to produce and to what bar. For every asset the game needs, state:

  • which binary produces it;
  • where the produced file lands in the workspace, and how the build wires it in (drawn directly, animated frame by frame, played through the particle runtime, posed through the voxel runtime, played via Web Audio);
  • the quality bar in real, testable terms, covering art direction, motion, the feel of the effects, and the character of the sound.

Where the game needs sound, name the packs the manifest declares and state that they are already present in the container, browsable with list-samples and list-instruments.

Follow the general asset-brief craft: set mood and tone, and leave the creative decisions to the model. Keep specs/assets.md and the produced-asset review points in lockstep, so every produced asset the reviewer checks traces to a line in this spec.

Author test-case.toml per the end-to-end schema with the full-stack differences.

  • type = "full-stack" identifies the type, and asset_dimension selects the run image: "2d" by default, or "3d" for the voxel and volumetric-particle tooling. Both are root keys, so they sit above the first table header.
  • The assets list is omitted. A full-stack case produces its own art.
  • The asset-generation tables are omitted. asset_kind, [sheet], [canvas], [tool], [output], [voxel], [model], [ui], [material], and [particle] are all rejected at resolution. Everything about the produced assets belongs in specs/assets.md.
  • [audio] packs declares the audio packs the run may reach, as a list of name@version refs. It is required, and the run container carries exactly what it names, so declare the full published set unless the case’s brief calls for a narrower palette. Order fixes the defaults; see [audio].
  • [build] is required and works exactly as end-to-end: explicit install and build, emitting a static site into dist/, build/, or out/. The build must bundle the committed asset files and run with the generation binaries absent, since validation and rebuild time have no access to them. A build that regenerates its own assets fails the load check.
  • packages ships a Test Cabinet runtime library into the run, and is valid for an end-to-end, full-stack, or game-jam case. Its common use is packages = ["@clockwyrks/particle-runtime"] so the game can play a produced system.json through the runtime’s ./canvas binding; a 3D case that ships a produced voxel model adds @clockwyrks/voxel-runtime. The case’s seeded workspace package.json must already depend on each declared package as file:./.vendor/packages/<name>, and resolution rejects a mismatch. Pair it with init = "npm install …" so the lockfile completes at seed time while [build].install stays npm ci.
  • [[domain]] entries must cover the produced assets as first-class quality dimensions. Hollowdeep rates a simulation domain for the code and a presentation domain for the produced art, motion, effects, and audio; the overall rating is the worst across the set. See Review.
  • variants, engines, the [toolchain] table, and the validators work exactly as end-to-end. [[reference]], [[proof]], and [[check]] are retained for shipped versions; a new case declares none.

description.md, changelog.md, and README.md, unchanged from end-to-end.

Validate by resolving and seeding, for every variant:

Terminal window
tcab prompt --test-case <slug> --version <version> --variant <variant>
tcab seed --test-case <slug> --version <version> --variant <variant>

prompt catches strict-mode template errors and manifest problems, including a forbidden asset-generation table and a malformed pack ref. seed writes the seeded repository to disk so you can confirm the seeded set, specs/assets.md included, is complete and self-contained and that no pre-provided assets/ leaked in. Resolve the declared packs against the registry with node scripts/ci/audio-packs-check.mjs. Lint the specs and prose with npm run lint:specs.

When the case is ready, exercise it with Run a Test Case; a full-stack run is scheduled onto the image its asset_dimension selects. Re-ingest the case before running if a backend already holds an earlier definition. See Running the Local Service Stack.