Director tools
The Game Director works only through these 35 tools: it never writes a file or runs code of its own. The Director in the Studio and Claude Code over gamewright mcp call the same registry. Every input is checked against schemas/v1/tools.schema.json before a tool runs. Generated from the registry and the schema.
Read (10)
Read tools look at the game and never change it.
game_summary read
Game summary
Where the game is: its brief, its template and the kits it runs; its plan, when it has one (each milestone, done or not, and the acceptance Playtests it still lacks); the pipeline stage (brief, template, systems, world, presentation, tuning), the open stages and the document kinds each allows (allows), and what each closed stage waits for (closed); the checkpoints (C1 brief and template approved, C2 first playable played); the L0 check; document counts per kind (the game's own and the template's); the person's own imported files (assets: what each is and the Sprites and Sounds that use it; prefer them); every pending proposal, oldest first, with what it waits for (the person, the proposals it builds on, or nothing because it is stale) and its report's headline; locks, KitRequests, and the next recommended step. Call it first in every conversation, and whenever you are unsure what to do next.
No input.
get_document read
Get document
One document by id, as the game has it: the game's own, or the template's default when the game has none (origin says which; revising a template document makes the game its own copy). Returns the canonical document, its content hash, its path and any locks; for an Asset that is a picture, the picture itself, to see how its frames are laid out.
| Field | Type | What it is |
|---|---|---|
id required | a document id like item.iron_sword: a lowercase kind prefix, a dot, then lowercase letters, digits, _ and . | Id of an existing document, e.g. item.iron_sword or level.forest_01. |
list_documents read
List documents
Every document of the game, template defaults included, optionally of one kind: id, kind, name, path, origin (game or template), status and content hash. Use get_document to read one.
| Field | Type | What it is |
|---|---|---|
kind | a document kind like Archetype | A document kind, as its kind field names it: Archetype, Item, RuleSet. |
document_schema read
Document schema
The JSON Schema of one document kind (Archetype, Item, RuleSet…), with every field's description, the kit vocabulary it accepts, where its files go, the pipeline stage it belongs to, and an example from this game or its template when there is one. Once there is a game (or one waits for the person), what comes from the kits it runs is in full and every other kit's part is one line (its kit and id); notRun gives the revise of game.json that enables each of those kits. def gives one part in full, from any kit: a $def by its name (ComponentMelee) or by its id (melee). Read it before create_document for a kind you haven't written in this conversation.
| Field | Type | What it is |
|---|---|---|
kind required | a document kind like Archetype | A document kind, as its kind field names it: Archetype, Item, RuleSet. |
def | string | One part of the kind's schema in full, whatever kit it comes from: a $def as the schema names it (ComponentMelee, Lock) or a component, action, pass, task or builder by its id (melee). Without it, the schema with only the kits this game runs in full. |
vocabulary read
Vocabulary
What the engine can do, generated from the kits' registrations: components, actions, events, functions (for expressions), generator passes, behavior tasks, model and sound builders, tour verbs, shared structs, and body plans (kind plan: the roles a rigged Model's joints play and the motion presets it can take, a gallop, a hop, a strut, a jump, a hurt, from the library or the game). With no input, an index: every kit, and one line per entry. With kit or kind, those entries in brief: each field in a line with its type, range and default, and the first two sentences of each description, which say when to use it. With id, that one entry whole (a document's builder, an action): read only what the change needs, since everything read is carried through the rest of the turn. Once there is a game, every kit and entry says whether this game runs it (enabled), and each kit it doesn't run gives the exact revise of game.json that enables it and the kits that come with it: put that edit in the same slice as what uses the kit. This is the engine's whole vocabulary, so there is no need to read engine source for its limits. When nothing here can say what the person wants, file_kit_request instead of approximating.
| Field | Type | What it is |
|---|---|---|
kit | a kit id like kit.melee: kit, a dot, then lowercase letters, digits and _ | |
id | string | One entry by its id, as the index or a document names it (a Model's builder, mesh.tree; an action, give): that entry in full and its kit. The cheapest way to read the one thing a change needs. |
kind | "component" | "action" | "event" | "function" | "pass" | "task" | "builder" | "tourVerb" | "struct" | "view" | "plan" | Which vocabulary: component, action, event, function, pass, task, builder, tourVerb, struct, view (what a kit draws and which Style slots it reads) or plan (a body plan's roles and the motion presets a rigged Model can take: gaits, jumps, a hurt). |
template_catalog read
Template catalog
The genre templates a game can start from. With no input, an index: each template's id, name, version and what it is in a line, when to use it and when not. With id, that template whole: the questions to ask the person before choosing it, the knobs a game may turn (value, range and why), what bots must show on it (acceptance), every kit a game on it runs (kits, with what they require; vocabulary says how to enable more), and the documents it provides by default, by kind (a game has them until it replaces one with a document of the same id). Pick the template whose useWhen matches the brief, then read it whole for its questions.
| Field | Type | What it is |
|---|---|---|
id | a template id like tpl.action_survival | One template's whole entry: its questions for the person, its knobs, what bots must show on it, its kits and the documents it provides. |
impact read
Impact
What changing one document reaches: the documents it references, those that reference it (directly, through ids or tune.<knob> expressions, and transitively), whether the bundle re-bakes, and which Playtest scenarios re-run. Use it before revising something many documents depend on.
| Field | Type | What it is |
|---|---|---|
id required | a document id like item.iron_sword: a lowercase kind prefix, a dot, then lowercase letters, digits, _ and . | Id of an existing document, e.g. item.iron_sword or level.forest_01. |
status read
Status
What is stale: whether the baked bundle matches the pack (or needs a bake), proposals whose files changed since they were made (they can only be rejected; propose your own again with replaces naming them), the L0 check, and the KitRequests on file.
No input.
history read
History
The game's changes read back, newest first: each one's title, who made it (you or the person), where it stands, the documents it writes, and every decision on it with what the person said (a rejection's reason). With document, only the changes to that document. Use it before you change something again, to see what was tried, rejected or undone there and why; each turn already opens with what happened since the last.
| Field | Type | What it is |
|---|---|---|
document | string | Only the changes that write this document (its id, or a path for other files). |
limit | integer | How many, newest first (default 20). |
assess_ask read
Assess an ask
Before you promise a new game or a big change, see what the engine can make of it: each word of the person's ask against the kits' vocabulary (what covers it, and words nothing covers), the templates whose "use when" it matches, what every kit does in a line, and the gaps already filed. A word nothing covers that names a thing (a lighthouse, a storm) is content documents can make; one that names something the player does (grapple, trade, build) that no kit covers is a real gap. Then tell the person plainly: what you can make as asked, what you will approximate and how, what can't be made yet (file_kit_request for it), and the nearest game you can make now.
| Field | Type | What it is |
|---|---|---|
ask required | string | Their words, as they said them. |
Propose (10)
Propose tools return a change set for the person to approve. Nothing in the game changes until they do.
propose_brief propose
Propose brief
Propose the game's brief (brief.json), the first thing the person approves: a working title, a one-sentence pitch, two or three pillars every later choice is checked against, the core loop (verbs, resources, goals, how the player loses), scope caps kept small, and the template it fits. Ask the person the template's required questions (template_catalog with its id) first. Each loop verb is looked up in the vocabulary; a verb nothing covers comes back as a warning, a gap to file with file_kit_request. Proposing again once it is approved revises the brief. Returns a proposal that waits for the person. With after (pending proposal ids), it builds on those proposals as if they were applied, and the person approves them first; use it so the next idea doesn't wait a round for the last. With replaces (your own proposal that still waits for the person), it takes that one's place: to fix a pending proposal, propose the whole of it again, fixed, naming it in replaces, instead of stacking a fix on it.
| Field | Type | What it is |
|---|---|---|
name required | string | The game's working title. |
pitch required | GameBrief document | |
pillars required | GameBrief document | |
template required | a template id like tpl.action_survival | The template the game fits best (template_catalog). |
coreLoop required | GameBrief document | |
scope required | GameBrief document | |
rationale required | string | Why this change, in one or two sentences, for the person reviewing it. |
after | list of a change id like chg.20260930_sword_damage | Pending proposals (change ids) this one builds on, in the order they apply. It is made and checked against the pack as it would be with them applied, and the person approves them first; a proposal they build on is included with them. Leave it out to build on the pack as approved. |
replaces | a change id like chg.20260930_sword_damage | Your own pending proposal (a change id) that this one takes the place of. To fix a proposal that still waits for the person, propose the whole of it again, fixed, and name it here; don't stack a fix on it. It becomes superseded (nobody has to decide it), and proposals built on it move onto this one when they still fit, or go stale saying why. Without after, this one builds on what it was built on. Never an applied or decided proposal, or one of the person's. |
create_game propose
Create game
Propose game.json: the game, pinned to a template by id and version ("1" takes the newest 1.x), with its title and root seed. Needs a brief (approved, or pending and named in after), and refuses when the pack already has a game. Once the person approves it the game runs on the template's defaults: playable at once when the template brings a place to play (template_catalog with its id: provides lists a WorldGen, Level, PlatformLevel or Dialogue), and with nothing to play until the first playable adds a level or a world when it brings none. Tell them which, and give them the play command once there is something to play. While it waits, the first playable (systems and the world, and revisions of the template's documents) can be proposed with after naming it; the look waits for C2 either way. Returns a proposal that waits for the person. With after (pending proposal ids), it builds on those proposals as if they were applied, and the person approves them first; use it so the next idea doesn't wait a round for the last. With replaces (your own proposal that still waits for the person), it takes that one's place: to fix a pending proposal, propose the whole of it again, fixed, naming it in replaces, instead of stacking a fix on it.
| Field | Type | What it is |
|---|---|---|
template required | object | |
id required | a game id like game.tideline | |
name required | string | The game's title as players see it. |
rootSeed required | integer | Unsigned 32-bit seed. Child seeds are derived by name path (deriveSeed), never by draw order. |
rationale required | string | Why this change, in one or two sentences, for the person reviewing it. |
after | list of a change id like chg.20260930_sword_damage | Pending proposals (change ids) this one builds on, in the order they apply. It is made and checked against the pack as it would be with them applied, and the person approves them first; a proposal they build on is included with them. Leave it out to build on the pack as approved. |
replaces | a change id like chg.20260930_sword_damage | Your own pending proposal (a change id) that this one takes the place of. To fix a proposal that still waits for the person, propose the whole of it again, fixed, and name it here; don't stack a fix on it. It becomes superseded (nobody has to decide it), and proposals built on it move onto this one when they still fit, or go stale saying why. Without after, this one builds on what it was built on. Never an applied or decided proposal, or one of the person's. |
create_document propose
Create document
Propose one whole new document of any kind (an Archetype, Item, Recipe, RuleSet, StateMachine, Tuning, WorldGen, Playtest…). Read its schema with document_schema first. Write meta as {"status": "draft", "provenance": {"createdAt": "2026-01-01T00:00:00Z", "createdBy": "agent", "license": "CC0-1.0"}}: the tool stamps the real time, author and tool. The file goes to <folder>/<name>.<kind>.json unless you give a path. A document with a template document's id replaces that default for this game. It is checked with the whole game (schemas, references, expressions, obtainability); problems come back with a pointer into the input, a message and a hint: fix them and call again, at most three times. Refused, naming the checkpoint, while the kind's pipeline stage isn't open. Use revise to change a document that exists, and propose_slice when several documents need each other. With after (pending proposal ids), it builds on those proposals as if they were applied, and the person approves them first; use it so the next idea doesn't wait a round for the last. With replaces (your own proposal that still waits for the person), it takes that one's place: to fix a pending proposal, propose the whole of it again, fixed, naming it in replaces, instead of stacking a fix on it.
| Field | Type | What it is |
|---|---|---|
document required | document | A whole pack document, of one of the content kinds. |
path | a relative path inside the pack, like levels/forest.level.json | Where to write it; left out, <folder>/<name>.<kind>.json by convention (archetypes/sentry.archetype.json). |
rationale required | string | Why this change, in one or two sentences, for the person reviewing it. |
after | list of a change id like chg.20260930_sword_damage | Pending proposals (change ids) this one builds on, in the order they apply. It is made and checked against the pack as it would be with them applied, and the person approves them first; a proposal they build on is included with them. Leave it out to build on the pack as approved. |
replaces | a change id like chg.20260930_sword_damage | Your own pending proposal (a change id) that this one takes the place of. To fix a proposal that still waits for the person, propose the whole of it again, fixed, and name it here; don't stack a fix on it. It becomes superseded (nobody has to decide it), and proposals built on it move onto this one when they still fit, or go stale saying why. Without after, this one builds on what it was built on. Never an applied or decided proposal, or one of the person's. |
revise propose
Revise
Propose edits to one document: each sets the field at a JSON Pointer to a value written as JSON text ("0.5", "\"chase\"", "{…}"), /- appends to a list, and null removes a field or list entry. Name a list item by its local id with item, and the pointer is then inside that item wherever it sits in its list (never count positions when an item has an id). Revising a template document makes it the game's own copy. Locked parts are refused, naming the lock. The result is checked with the whole game, and problems point at the edit that caused them. Returns a proposal with a field-level diff. With after (pending proposal ids), it builds on those proposals as if they were applied, and the person approves them first; use it so the next idea doesn't wait a round for the last. With replaces (your own proposal that still waits for the person), it takes that one's place: to fix a pending proposal, propose the whole of it again, fixed, naming it in replaces, instead of stacking a fix on it.
| Field | Type | What it is |
|---|---|---|
id required | a document id like item.iron_sword: a lowercase kind prefix, a dot, then lowercase letters, digits, _ and . | Id of an existing document, e.g. item.iron_sword or level.forest_01. |
edits required | list of edit | |
rationale required | string | Why this change, in one or two sentences, for the person reviewing it. |
after | list of a change id like chg.20260930_sword_damage | Pending proposals (change ids) this one builds on, in the order they apply. It is made and checked against the pack as it would be with them applied, and the person approves them first; a proposal they build on is included with them. Leave it out to build on the pack as approved. |
replaces | a change id like chg.20260930_sword_damage | Your own pending proposal (a change id) that this one takes the place of. To fix a proposal that still waits for the person, propose the whole of it again, fixed, and name it here; don't stack a fix on it. It becomes superseded (nobody has to decide it), and proposals built on it move onto this one when they still fit, or go stale saying why. Without after, this one builds on what it was built on. Never an applied or decided proposal, or one of the person's. |
propose_slice propose
Propose slice
Propose one idea that spans several documents as one change set, checked as one pack: kits enabled in game.json, the items, the recipe that needs them, the creature and its brain, the place they live, the Playtest that proves it. Each entry creates a whole document ({"create": {"document": {…}, "path"?}}, as create_document takes it) or revises one ({"revise": {"id", "edits"}}, as revise takes them); each document once. At most 12 documents: keep it one idea the person can read in one sitting, and put the next idea in its own slice with after naming this one. Every entry's kind must be open at the current stage; problems point at /entries/<i>/…. The person approves or rejects the slice whole. With after (pending proposal ids), it builds on those proposals as if they were applied, and the person approves them first; use it so the next idea doesn't wait a round for the last. With replaces (your own proposal that still waits for the person), it takes that one's place: to fix a pending proposal, propose the whole of it again, fixed, naming it in replaces, instead of stacking a fix on it.
| Field | Type | What it is |
|---|---|---|
title required | string | The idea, as one imperative line: 'Add the shell gathering loop'. |
entries required | list of slice entry | |
rationale required | string | Why this change, in one or two sentences, for the person reviewing it. |
after | list of a change id like chg.20260930_sword_damage | Pending proposals (change ids) this one builds on, in the order they apply. It is made and checked against the pack as it would be with them applied, and the person approves them first; a proposal they build on is included with them. Leave it out to build on the pack as approved. |
replaces | a change id like chg.20260930_sword_damage | Your own pending proposal (a change id) that this one takes the place of. To fix a proposal that still waits for the person, propose the whole of it again, fixed, and name it here; don't stack a fix on it. It becomes superseded (nobody has to decide it), and proposals built on it move onto this one when they still fit, or go stale saying why. Without after, this one builds on what it was built on. Never an applied or decided proposal, or one of the person's. |
vary propose
Vary
Propose 2 to 6 options for chosen fields of one document, for the person to choose between: numbers spread across their range around the current value, enums take other values, booleans flip, hex colours turn round the hue wheel. The options come from the seed (the same call gives the same options) and form one variation group: approving one rejects the others. Use it where taste matters (how fast, how dark, which colour); give the person the options' labels to choose from. With after (pending proposal ids), it builds on those proposals as if they were applied, and the person approves them first; use it so the next idea doesn't wait a round for the last. With replaces (your own proposal that still waits for the person), it takes that one's place: to fix a pending proposal, propose the whole of it again, fixed, naming it in replaces, instead of stacking a fix on it.
| Field | Type | What it is |
|---|---|---|
id required | a document id like item.iron_sword: a lowercase kind prefix, a dot, then lowercase letters, digits, _ and . | Id of an existing document, e.g. item.iron_sword or level.forest_01. |
targets required | list of vary target | |
count required | integer | How many options, 2 to 6. |
seed required | integer | Unsigned 32-bit seed. Child seeds are derived by name path (deriveSeed), never by draw order. |
rationale required | string | Why this change, in one or two sentences, for the person reviewing it. |
after | list of a change id like chg.20260930_sword_damage | Pending proposals (change ids) this one builds on, in the order they apply. It is made and checked against the pack as it would be with them applied, and the person approves them first; a proposal they build on is included with them. Leave it out to build on the pack as approved. |
replaces | a change id like chg.20260930_sword_damage | Your own pending proposal (a change id) that this one takes the place of. To fix a proposal that still waits for the person, propose the whole of it again, fixed, and name it here; don't stack a fix on it. It becomes superseded (nobody has to decide it), and proposals built on it move onto this one when they still fit, or go stale saying why. Without after, this one builds on what it was built on. Never an applied or decided proposal, or one of the person's. |
restyle propose
Restyle
Propose a change to the game's look: switch to another Style (the game's own, or one its template supplies) and/or edit the style it uses, with the same edits as revise. A template's style becomes the game's own copy when edited. Belongs to the presentation stage, so it waits for checkpoint C2 (the person played the first playable). Its verification plays the game before and after and must find every state hash the same, since a look never changes play. Look at before and after with preview before describing the result. With after (pending proposal ids), it builds on those proposals as if they were applied, and the person approves them first; use it so the next idea doesn't wait a round for the last. With replaces (your own proposal that still waits for the person), it takes that one's place: to fix a pending proposal, propose the whole of it again, fixed, naming it in replaces, instead of stacking a fix on it.
| Field | Type | What it is |
|---|---|---|
style required | a style id like style.tideline | |
edits required | list of edit | |
rationale required | string | Why this change, in one or two sentences, for the person reviewing it. |
after | list of a change id like chg.20260930_sword_damage | Pending proposals (change ids) this one builds on, in the order they apply. It is made and checked against the pack as it would be with them applied, and the person approves them first; a proposal they build on is included with them. Leave it out to build on the pack as approved. |
replaces | a change id like chg.20260930_sword_damage | Your own pending proposal (a change id) that this one takes the place of. To fix a proposal that still waits for the person, propose the whole of it again, fixed, and name it here; don't stack a fix on it. It becomes superseded (nobody has to decide it), and proposals built on it move onto this one when they still fit, or go stale saying why. Without after, this one builds on what it was built on. Never an applied or decided proposal, or one of the person's. |
file_kit_request propose
File kit request
File a gap in the vocabulary as a KitRequest document: what the game needs that no kit can say, examples of use, the registration a kit would add (in kit.json's shape: category, id, fields), and which call hit the gap. Use it instead of approximating what the person asked for. Any stage. Returns a proposal; the gap counts toward the engine's roadmap. With after (pending proposal ids), it builds on those proposals as if they were applied, and the person approves them first; use it so the next idea doesn't wait a round for the last. With replaces (your own proposal that still waits for the person), it takes that one's place: to fix a pending proposal, propose the whole of it again, fixed, naming it in replaces, instead of stacking a fix on it.
| Field | Type | What it is |
|---|---|---|
name required | KitRequest document | |
need required | KitRequest document | |
examples required | KitRequest document | |
proposed required | KitRequest document | |
hitBy | KitRequest document | |
rationale required | string | Why this change, in one or two sentences, for the person reviewing it. |
after | list of a change id like chg.20260930_sword_damage | Pending proposals (change ids) this one builds on, in the order they apply. It is made and checked against the pack as it would be with them applied, and the person approves them first; a proposal they build on is included with them. Leave it out to build on the pack as approved. |
replaces | a change id like chg.20260930_sword_damage | Your own pending proposal (a change id) that this one takes the place of. To fix a proposal that still waits for the person, propose the whole of it again, fixed, and name it here; don't stack a fix on it. It becomes superseded (nobody has to decide it), and proposals built on it move onto this one when they still fit, or go stale saying why. Without after, this one builds on what it was built on. Never an applied or decided proposal, or one of the person's. |
propose_plan propose
Propose a plan
For a big ask (more than a turn or two of work: several systems, many levels, a whole genre), propose the way there as the brief's plan: the person's ask in their words, then three to eight milestones in the order you will build them, each a step a player can play (outcome) with the Playtests that will prove it (acceptance: test ids, written with that milestone's own work). The person approves it once; then build one milestone at a time, and when its acceptance Playtests are in the game and pass, call complete_milestone. Milestones already done stay as they are; proposing again changes, adds or drops the open ones. Needs a brief (approved, or pending and named in after). Returns a proposal that waits for the person.
| Field | Type | What it is |
|---|---|---|
ask required | string | What the person asked for, in their words. |
milestones required | list of object | The steps still to build, in the order you will build them: three to eight is usual. |
rationale required | string | Why this change, in one or two sentences, for the person reviewing it. |
after | list of a change id like chg.20260930_sword_damage | Pending proposals (change ids) this one builds on, in the order they apply. It is made and checked against the pack as it would be with them applied, and the person approves them first; a proposal they build on is included with them. Leave it out to build on the pack as approved. |
replaces | a change id like chg.20260930_sword_damage | Your own pending proposal (a change id) that this one takes the place of. To fix a proposal that still waits for the person, propose the whole of it again, fixed, and name it here; don't stack a fix on it. It becomes superseded (nobody has to decide it), and proposals built on it move onto this one when they still fit, or go stale saying why. Without after, this one builds on what it was built on. Never an applied or decided proposal, or one of the person's. |
complete_milestone propose
Complete a milestone
Mark a milestone of the plan done, the only way one is: its acceptance Playtests must be in the game as approved (pending proposals don't count), and each is run now through L2. When every scenario of every one passes, it proposes the milestone done with what passed as evidence; when any doesn't, nothing is proposed and the answer says which and why, to fix first. Call it when you believe a milestone is built, never to check progress.
| Field | Type | What it is |
|---|---|---|
milestone required | a slug: lowercase letters, digits and _, starting with a letter (at most 48) | What the step is, as a slug (first_room, night_raids): never its place in the list. |
Run (8)
Run tools check, bake, play and draw the game. They write only what can be made again: bundles, reports and pictures.
validate run
Validate the pack
Check the whole pack as it is on disk, without running it (L0): every document against its schema, references, expressions and their types, state machines, obtainability of items, and whether it bakes. Fast (under a second). Use it after any change and before asking the person to decide. Returns pass or fail, and every error as file, JSON pointer, message and hint, so you can repair the exact field. It never changes the pack.
No input.
bake run
Bake the pack
Bake the pack into a bundle the player runs: resolve the template, fill defaults, compile every expression, hash everything. The same pack always gives the same bundle. Returns the bundle's folder and hash, or the problems that stop it baking. playtest, preview and play_command bake for you; use this when you only need the bundle or its hash.
No input.
playtest run
Playtest
Run the verification ladder and return a short report: L0 spec, L1 boot (600 idle ticks twice: the same state, a clean log), L2 play (every Playtest scenario through the engine, with metrics from its trace: crashes and errors, determinism, time to first reward, the longest stretch with nothing happening, action diversity, deaths and their causes, and how hard it was for the player: damage taken, blows landed and taken, time to kill, chases, escapes, the closest a chase came and how long the player kept away, before and after on a proposal), and, when asked, L3 frames (named tour shots, checked for blank frames, no change after input, and missing subjects; slow, it renders). A rung runs only when the ones below it are green. With changeId, it verifies that proposal: the pack as the proposal would leave it, with every Playtest compared against the pack as it is, and a scenario that goes from green to red is named first in the headline as a REGRESSION; the report is recorded on the proposal. A proposal that touches only the look (styles, themes, models, sounds, sprites, screens, the camera, the game's choice of them, or an Archetype's looks: its sprite, poses, model, cues or name) must leave play exactly as it was: L1's state hash and every scenario's must equal the pack's before it, or the report is red with CHANGED PLAY (restyle.changed_play); with L3 each shot comes back beside the same shot before the change (beforeAfter). The answer lists each rung, what regressed, what is red and why, each scenario's numbers, and what couldn't be checked; the full report is in the file it names. Read it before you describe the game or ask the person to decide; never claim anything it doesn't show.
| Field | Type | What it is |
|---|---|---|
rungs | list of "L0" | "L1" | "L2" | "L3" | The rungs to run, lowest first: L0 spec, L1 boot, L2 play (every Playtest, with trace metrics), L3 frames (named shots with property checks; slow). Default L0, L1 and L2. L4 judge and L5 web are not offered here: a person asks for them with gamewright verify --level (L4 spends money on a vision model; L5 needs a current web export). |
seeds | list of integer | Run each scenario on these seeds instead of its own. |
scenarios | list of a playtest id like test.stealth | Only these Playtests (default: every one in the pack). |
changeId | a change id like chg.20260930_sword_damage | A proposal to verify; its report is recorded on it. |
preview run
Preview
Draw the game and return the pictures, small enough to look at. what: world (the whole world, or the view at the spawn when the engine can't draw an overview yet), place (the view at a named place or beside an entity: name), model (a Model on its own, or where the game shows it: name), screen (what the player sees, HUD included). screen opens one of the game's Screens over any of them, as a person reaches it: an app on the slate (screen: ui.carry), the title over the game (ui.title); the HUD is what play shows anyway, and a part of it shown only while its when holds (an end card) can't be opened, so play to it in a Playtest with a shot. No tour can open an app, so preview each app you add or change, with phone: true too. In a game of levels (Levels or PlatformLevels), level goes to any of them first, as a level select screen would, so screen, place and world show that level with its things where the player meets them; place also takes a thing a level spawns (caves/crawler.5.3) or an archetype id (its first thing there) and goes to the level that has it, and says which levels have it when it can't tell which you mean. hours draws one picture per hour of the day, side by side. phone: true draws it as a phone held upright shows it, as L3's phone pass does (the frame beside the game's touch controls, kit.ui's text bigger and each Screen in less room, hints naming the touch controls), with phone_text_fits and phone_text_size in its checks: look at one after any change to a Screen. With changeId it draws the game as that pending proposal would leave it, as its verification plays it; before: true sets the game before it beside it (left, or above with several hours). Look at every image before you describe it; each caption says what it shows and whether a frame came out blank. Use it before and after any change to the look. It takes a while: frames render one job at a time on a shared machine.
| Field | Type | What it is |
|---|---|---|
what required | "world" | "place" | "model" | "screen" | |
name | string | The place or entity for place, the Model id for model. In a game of levels, place also takes a thing a level spawns (caves/crawler.5.3: <level>/<archetype>.<x>.<y>) or an archetype id (its first thing in the level), and goes to the level that has it. |
level | a document id like item.iron_sword: a lowercase kind prefix, a dot, then lowercase letters, digits, _ and . | A level to go to first: a Level or PlatformLevel id, whichever the game plays (default: where the game starts, or the level that has the place's name). |
screen | a screen id like ui.hud | A Screen to hold open over the view, as a person reaches it: an app on the slate opens as its key opens it (ui.carry), the title is drawn over the game as on the title (ui.title), and the HUD is what play shows anyway (ui.hud). Only a Screen the game shows: its manifest flow's title, HUD and apps, and the menu's pages every game has (ui.pause, ui.options: the game's own of that id, else kit.ui's). A part of the HUD shown only while its when holds (an end card) can't be opened: it shows where the game reaches it, so take a shot there in a Playtest that plays to it. With phone: true, the Screen as an upright phone lays it out. Look at an app after any change to it (default: none opened). |
hours | list of number | Hours of the day to draw, one image each, side by side (default: the game's own hour). |
seed | integer | The world seed (default: the game's root seed). |
changeId | a change id like chg.20260930_sword_damage | A pending proposal: draw the game as it would leave it, on the proposals it builds on (default: as approved). |
before | boolean | With changeId, also draw the game before it, beside it. |
phone | boolean | Draw it as a phone held upright shows it (390x844 points, as L3's phone pass and the deploy's phone visit do): the frame at the size a person's run renders, beside the game's touch controls, kit.ui's text drawn big enough to read there and each Screen laid out in the smaller room that leaves, its hints naming the touch controls. Its checks are phone_text_fits and phone_text_size, by the rules of that visit. Look at a phone after any change to a Screen (default: a monitor's frame). |
play_command run
How to play it
Bake the pack and return the exact command the person runs to play it in a window, with sound. Give it to the person whenever the game becomes playable or changes in a way they should feel; it doesn't run the game itself.
No input.
try run
Try a draft
Run an experiment without proposing it. Give a draft as propose_slice takes its entries (create or revise, each document once, at most 12), with after to build on pending proposals. It is checked as a proposal would be, runs up the ladder (L0 to L2; rungs adds L3, scenarios and seeds narrow it), and every Playtest is compared with the pack it builds on: a scenario it turns red leads as a REGRESSION, and each scenario's numbers come back before and after. Returns the report's digest and the diff. Nothing is recorded and nothing waits for the person. Use it to test a hunch; propose what you mean to keep.
| Field | Type | What it is |
|---|---|---|
entries required | list of slice entry | |
after | list of a change id like chg.20260930_sword_damage | Pending proposals (change ids) this one builds on, in the order they apply. It is made and checked against the pack as it would be with them applied, and the person approves them first; a proposal they build on is included with them. Leave it out to build on the pack as approved. |
rungs | list of "L0" | "L1" | "L2" | "L3" | L0 spec, L1 boot, L2 play, L3 frames (slow). Default: what a proposal of it would get. |
scenarios | list of a playtest id like test.stealth | Only these Playtests (default: every one in the pack). |
seeds | list of integer | Run each scenario on these seeds instead of its own. |
drive run
Drive the game
Play the game by a few tour lines, as a person would, and see what happened. The lines are a Playtest's steps (the tour language, and the verbs the game's kits add): press confirm, await control 5, goto prop:driftwood, use, await taken:driftwood 1, wait 2, shot name with player (boot game comes first unless you give a boot line). An unknown verb stops it and says so. It says whether the tour ran to its end or where it stopped and why, the game's events along the way by count, and how it ended. With shots: true it also draws the tour's shot lines and returns the frames (slow: it renders); without, it is quick. With changeId it drives the game as that pending proposal would leave it. Use it to check how something plays before you claim it does; a Playtest is still what keeps it working.
| Field | Type | What it is |
|---|---|---|
steps required | list of string | Tour lines, one command each, as a Playtest's steps (press confirm, goto prop:driftwood, use, await taken:driftwood 1, wait 2, shot name with player): boot game comes first unless you give a boot line. |
changeId | a change id like chg.20260930_sword_damage | Drive the game as this pending proposal would leave it. |
shots | boolean | Draw the tour's shot lines (slow: it renders); without it nothing is drawn and it is quick. |
ticks | integer | The most ticks it may run (default 3600: a minute at 60 Hz). |
remember run
Remember a note
Keep a short note for later conversations about this game: something the person prefers or dislikes (in their words where you can), a decision and its reason, a thing to avoid. It goes in memory.md, which you are shown at the start of every turn, in every conversation, and which the person can read and change. One fact a note, in plain words. Not for what the game already records (its documents, the brief, the change history), and not for this turn's progress. Memory holds 6000 characters in all.
| Field | Type | What it is |
|---|---|---|
note required | string | One fact in plain words: a preference of the person's, a decision and its reason, a thing to avoid. |
Decide (7)
Decide tools belong to the person. The Director in the Studio never has them; the Studio's own buttons do this. Over MCP they are marked destructive, so Claude Code asks before it runs one, and each says to call it only when the person has asked in their own words.
approve decide
Approve change
Apply a proposed change set to the pack: the whole pack is validated as it would be first, every file is written or none, and it is committed when the pack is a git repository. Only call this after the person has explicitly asked for this decision in their own words; never on your own judgment, and never to tidy up. Approving one option of a variation group rejects the others. A proposal whose files changed since it was made is marked stale and not applied. Returns the applied change and its commit.
| Field | Type | What it is |
|---|---|---|
changeId required | a change id like chg.20260930_sword_damage | Change set id. The same id names the change set everywhere: its file, undo (inverseOf), revisions (supersedes) and the decide tools. |
reject decide
Reject change
Decline a proposed or stale change set; the pack is untouched and the proposal stays in history as rejected. Only call this after the person has explicitly asked for this decision in their own words; never on your own judgment, and never to tidy up.
| Field | Type | What it is |
|---|---|---|
changeId required | a change id like chg.20260930_sword_damage | Change set id. The same id names the change set everywhere: its file, undo (inverseOf), revisions (supersedes) and the decide tools. |
undo decide
Undo
Undo an applied change set by applying its inverse as a new change set (history is never rewritten; replaced files come back byte for byte), and commit it when the pack is a git repository. Undoing an undo re-applies the change it undid. Refused when the files have changed since. Only call this after the person has explicitly asked for this decision in their own words; never on your own judgment, and never to tidy up. Returns the change now in effect.
| Field | Type | What it is |
|---|---|---|
changeId required | a change id like chg.20260930_sword_damage | Change set id. The same id names the change set everywhere: its file, undo (inverseOf), revisions (supersedes) and the decide tools. |
redo decide
Redo
Re-apply a change set that was undone, if its files are still as it expects. Takes the id of the undone change, not of its undo. Only call this after the person has explicitly asked for this decision in their own words; never on your own judgment, and never to tidy up.
| Field | Type | What it is |
|---|---|---|
changeId required | a change id like chg.20260930_sword_damage | Change set id. The same id names the change set everywhere: its file, undo (inverseOf), revisions (supersedes) and the decide tools. |
lock decide
Lock
Lock a document (no item and no pointers: the whole document), a list item (item, no pointers), or parts of either (pointers). Locked parts are never regenerated or changed until the person unlocks them, and a lock on an item follows it when the list changes around it. Applied at once as its own change set, so it can be undone. Only call this after the person has explicitly asked for this decision in their own words; never on your own judgment, and never to tidy up.
| Field | Type | What it is |
|---|---|---|
id required | a document id like item.iron_sword: a lowercase kind prefix, a dot, then lowercase letters, digits, _ and . | Id of an existing document, e.g. item.iron_sword or level.forest_01. |
item | a slug: lowercase letters, digits and _, starting with a letter (at most 48) | Local id of a list item in the document (an ability, a part, a state). The pointers are then inside that item, and the lock follows it wherever it moves in its list. |
pointers required | list of a JSON Pointer to a field, like /stats/hp | |
reason | string |
unlock decide
Unlock
Remove locks from a document (no item and no pointers: every lock, and a locked document becomes approved; item and no pointers: every lock on that item), so those parts can change again. Applied at once as its own change set, so it can be undone. Only call this after the person has explicitly asked for this decision in their own words; never on your own judgment, and never to tidy up.
| Field | Type | What it is |
|---|---|---|
id required | a document id like item.iron_sword: a lowercase kind prefix, a dot, then lowercase letters, digits, _ and . | Id of an existing document, e.g. item.iron_sword or level.forest_01. |
item | a slug: lowercase letters, digits and _, starting with a letter (at most 48) | Local id of a list item in the document (an ability, a part, a state). The pointers are then inside that item, and the lock follows it wherever it moves in its list. |
pointers required | list of a JSON Pointer to a field, like /stats/hp | |
reason | string |
mark_played decide
Mark first playable played
Record checkpoint C2: the person has played the first playable. The look (the presentation stage) waits for it. Only call this after the person has explicitly asked for this decision in their own words; never on your own judgment, and never to tidy up. Only when they say they have played this game; never because a playtest passed. Put what they said about it in note. Applied at once as its own change set, so it can be undone.
| Field | Type | What it is |
|---|---|---|
note | string | What the person said about it, in their words. |
dressFirst | boolean | True when the person chose to dress the game before playing it (the Studio's Dress it first): C2 is recorded as waived, and the look opens. A look-only change still cannot change play (the restyle gate). |