Skip to content

Manifests

A game jam declares its contents in its own game-jam.toml manifest, parsed through a small dedicated schema holding the handful of fields a theme-only build has. Parsing rejects any unknown key, so a manifest that reaches for test-case machinery (difficulty, variants, type, [[spec]], and the rest) fails with a clear error.

Game jams live in a sibling top-level directory, laid out by slug and version:

game-jams/<slug>/<version>/game-jam.toml

A jam is themed rather than tiered, so there is no <type>/<difficulty> grouping. Discovery folds the folder into the same catalog as test-cases/, so a jam’s slug shares the one global slug namespace and may not collide with a test-case slug. The folder location and the game-jam.toml filename are what mark a case as a jam; there is no type field.

A jam declares only these keys. All paths resolve relative to the version folder.

KeyRequiredMeaning
slug✅Stable identity (the definition-store key). Identical on every version of the folder.
name✅Human-readable display name.
changelog✅Per-version changelog entry (a Markdown file). Not seeded.
prompt✅The theme brief (a Handlebars template). See below.
[build]✅The fixed build interface: install and build, both stated, neither empty, no build.module. Same as a full-stack case.
tags—Free-form tags for browsing and search.
summary—One- or two-sentence abstract on the jam card. Not seeded.
description—Site-facing prose (a Markdown file). Not seeded.
max_runtime_hours—Wall-clock cap for the session and for each setup step, defaulted when omitted. Also the model’s stated time budget.
experimental—Hide the version until a deployment opts in.
workspace—Starter workspace directory seeded into the run root.
init—Command run once after the workspace is seeded, before the harness starts.
packages—The @clockwyrks/* runtime libraries the build imports, as on a full-stack case.
engines—The engines a run of this jam may select, as on a test case. Defaults to ["none"].
[audio]—The audio packs a run may reach. See below.
[[review_item]]—Graded review categories. See below.

Two fields a test case carries are absent, and declaring either is a parse error.

A jam is unclassified: the model decides what to build from the theme, so there is no tier to bracket it into. The resolved case carries an unrated placeholder internally to keep the shared shape uniform, and jams are excluded from the tiered test-case catalog.

A jam is one theme, so it has no variants. A differently themed jam is a different jam. Resolution runs a jam as a single implicit default variant, synthesized for the author.

The prompt is Handlebars, rendered per run. It states the theme and, where the author wants it restated, the playable and enjoyable bar. The standing game-jam directive is prepended automatically, so the template covers only what is specific to this jam.

Alongside {{workspace}} (the absolute in-container project root), a prompt may reference {{time_limit_hours}}, the run’s wall-clock budget in hours derived from max_runtime_hours. State the budget so the model can pace itself, and tell it to run date in the container to read the current time.

A jam produces its own sound during the run, and [audio] declares the packs sfx-sample and music may reach. It behaves exactly as it does on a full-stack case: packs is the only key, each entry is a name@version ref, the run container is staged with those packs alone, and the first declared pack of each kind is what a tool config naming none plays. A jam declares the full published set unless its theme calls for less:

scripts/ci/audio-packs-check.mjs requires the declaration on every jam version.

A jam is reviewed on graded categories rather than a pass/fail checklist. See Evaluation for the scale and how the points work. There are two ways to declare them.

Declaring no [[review_item]] gets the standard set injected at resolution: Playability, Fun, Theme, Presentation, Audio, Polish, and Creativity, each of weight 1. This is the expected path and keeps every jam comparable.

Declaring [[review_item]] tables replaces that set with the author’s own, to weight or specialize the categories. The type forces every category to be graded, each is worth weight × 10 points, and the same id, title, and text rules apply as elsewhere. The id overall is reserved for the reviewer’s whole-game grade. A jam declares no scoring domains, so a category carries no domain, and a graded category carries no automated validation script, since it has no pass/fail verdict to decide. The [review] format = 2 categories grammar is binary, so a jam uses the [[review_item]] tables instead.