Docs Design

Contents

Roadmap

Each milestone ends with something you can play or watch, and a check anyone can rerun. Where the plan departs from the brief, the change is marked Change with the reason. Read with ARCHITECTURE.md.

The spine: M1 proves the engine can make the owner's kind of game from data alone. M2 proves the Director can make it from a conversation. Everything after widens "any game".

Now (2026-10-09): the audit's plan. A critical audit against best-in-class (the Studio, the Director, the engine, the web, the market, engineering) ranked everything still missing and set the order of work in waves: safety and gates, what a person feels in their first session, the first ten minutes, the Director's depth, what games can be, distribution. It lives in design/audit-2026-10.md, checked off as items land; the milestones below are the long-form record.

M0 Foundations (done 2026-09-30)

  • Repo: README, CLAUDE.md, ADRs 0001–0011, research, license placeholder, .env.example.
  • Core foundation, copied from Reelwright with attribution (core/UPSTREAM.md): strict JSON, JSON Pointer, diagnostics, JCS hashes, canonical files, named seeds, PCG32, pcg_hash, the schema registry, validator and explainer, the structured-output lint, tool-schema bundling, and codegen to TypeScript and GDScript (with a GDScript validate()).
  • Engine skeleton: the engine/ project, GwSeed, GwHash, GwPcg32 against the shared vectors, the engine CLI scene, vendored gdUnit4, image compare.
  • Tooling: toolchain.json with Godot and its export templates, installers, doctor.sh, engine-test.sh, engine-check.sh, heavy.sh, the hidden-input check, check-all.sh, CI.
  • Web: a Next.js landing page in web/, deployed to Vercel and checked live.
  • Proof of the riskiest assumption: seed, hash and PCG32 vectors hold in a web export, not just natively.
  • Try it: tools/check-all.sh is green; the landing page is live at https://gamewright.diy.
  • Result: every gate passes locally (204 core tests, 48 engine tests at the time). The seed, hash and PCG32 vectors hold in both web builds as well as natively (research/web-vectors.md). Not yet confirmed: the CI run on GitHub, because gh isn't authenticated on the dev box.

M1 The player and the Tideline slice (no AI) — landed (A6 and A7 partial)

The engine's first game is a small slice in the spirit of unspent-ortho, written by hand as a Game Pack (examples/tideline/) and run by the generic player. The slice is specified in research/unspent-ortho-study.md §4; the design is docs/design/m1-player.md.

  • Schemas v1.0 for the kinds the slice needs: GameManifest, Template, Theme, Style, Stats, Archetype, Item, Recipe, LootTable, RuleSet, StateMachine, WorldGen, Biome, Model, Sound, Screen, InputMap, CameraRig, Tuning, Playtest, Tour. Plus vocab.schema.json generated from kit registrations.
  • Core: validate (schema, semantics, obtainability), the Expr compiler, bake, play, shot, verify (L0–L2).
  • Player runtime: bundle loader and checks, fixed-tick sim with input frames, the event bus, the kit registry with declared order, state hash, the Expr VM, the rules and state-machine runners, saves with a world stamp, the playtest bridge, tours, and the frame server.
  • Kits for the slice: world.tiles (levels, grounds, step and cliff rules, wading), the worldgen passes (height, terraces, water, scatter, spawns, reachability), move.ground, perception (sight cone, hearing, dark, cover, lamp), brain.fsm, melee (windup, active, recovery, i-frame dodge, plate and working part), harvest, inventory, crafting, clock.daynight, light.carried.
  • Presentation for the slice: the lit_ortho3d profile (Compatibility only), the ortho camera rig with texel snap and stipple occlusion, the terrace mesher with chunks, the mesh kit and 6–8 archetype builders (pine, driftwood, boulder, wreck, sentry, the player figure, campfire), the pooled light budget and shader warm-up, a Screen-driven HUD and two slate apps, and the synth baked to buffers with a mix sheet.
  • Web: the no-threads web player loads the Tideline bundle; the landing page links to it.
  • Acceptance (research/unspent-ortho-study.md §4.3, adapted):
    1. World digests for seeds 1–5 are identical across runs and between desktop and web.
    2. Editing any generator document changes the world stamp; an old save is refused by name.
    3. The proof tour runs from the title with no cheats: gather, make the campfire, dusk, night, lamp, the sentry's round, noticed, the tell, dodge, hit the back, the kill, the scrap, save, load, same state. Every shot names its subject.
    4. Tactics, not stats: a dodging bot wins at least 80% of 20 seeded fights; a trading bot loses at least 80%.
    5. Stealth ordering: notice distance for a lamp-lit night ≥ standing day > standing night > crouched in cover at night.
    6. Budgets: the sentry ≤ 6 draws and 3,600 triangles; each chunk ≤ 6 draws; no shader first compiled at the lamp, the fire or the fight.
    7. The web build boots in headless Chromium with no errors, has sound after the first key, and keeps a save across a reload.
    8. Frame checks: the night is dark, the lamp pool is bright, the sentry reads darker than the turf at noon, and no crown covers the player.
    9. Every emitted cue maps to a sound, and every loop is seamless.
    10. Boundary: the slice's content lives only in its pack. A lint rejects engine code that mentions a pack id. Anything the slice needed from the engine landed as a generic kit with its own tests.
  • Play it: at gamewright.diy/play, or gamewright play examples/tideline (or tools/play.sh --bundle B); a local browser run is tools/web.sh --bundle=B --serve.
  • Result (T6, 2026-09-30): Tideline is a Game Pack in examples/tideline/ (54 documents on tpl.action_survival), played by the generic player on the desktop and in the browser. Its README says how to play it. Every acceptance check below was run on the pack itself; the frames are docs/images/m1/tideline-*.png. The template under it now runs every kit the genre needs and brings a world, a player, a Style, sounds and the slate, so a pack with only game.json bakes and boots playable (core/test/template-game.test.ts).
    1. Met. node core/src/cli/main.ts digest --seed N examples/tideline, twice for seeds 1–5: the same digest both runs (d31018ea…, f231926b…, 0f403886…, 6c160a69…, d2960e75…). The browser gives the same five (tools/web.sh --bundle=B --tour=playtests/web/digest-N.tour, a tour that only boots). Getting there found a real bug: the HUD's held(self) filled in the starting items, so a game a view had drawn differed from the same game unwatched. kit.inventory now fills them at spawn.
    2. Met. Raising the driftwood scatter chance from 0.22 to 0.23 in gen.tideline changed the stamp (5264dd17… to 0f194759…). A save made before the edit is refused with save.stamp_mismatch: the save was made under another world stamp: the generator documents or root seed were rebaked. The same save loads under the old stamp.
    3. Met. playtests/proof.tour in the player (tools/play.sh --tour … --shots DIR, offscreen) ends tour proof done at tick 4591 with 13 shots, each naming its subjects. It goes from the title with no cheats: three driftwood, two stones, dusk, the campfire, night, the lamp, the round, noticed, the tell, a dodge, the tactics bot on the sentry's back until it is killed, the scrap, save, quit to the title, load, same state. verify L2 runs it as test.proof: no errors, and its asserts hold (one fire made, the sentry stilled, never downed).
    4. Met. On the pack's own documents (engine/tests/kits/tideline/gw_tideline_a4_test.gd, which runs the bundle baked from examples/tideline), the tactics bot wins 18 of 20 seeded fights and the trader loses 20 of 20. In the game's world, test.tactics kills the sentry without being downed, and test.trading is downed.
    5. Met. Notice distance is 12.0 m with a lamp at night, 12.0 standing by day, 6.0 standing at night and 1.32 crouched in cover at night. Behind the cone only close range counts (3.36 m by day, 1.68 at night, against 12.0 in front). Hearing is unchanged by cover and dark (walking 4.95 m in each) and follows loudness (running 9.92, crouching 1.96, taking a prop 6.0). test.stealth in the world: crouched at night by round_c, unseen for 90 s, then seen once the lamp is lit.
    6. Partly measured. Models: every one builds within its budget, and the sentry is 702 triangles in 2 draws (budget 6 and 3,600). Chunks: 36, the worst 4 draws. Shaders: the player warms up 10 programs before the first tick (12 after a load). But the Compatibility renderer's pipeline-compilation counters read 0 throughout, even during the warm-up, so "nothing compiled at the lamp, the fire or the fight" could not be measured (engine/tests/present/shots/game_frames.sh reads them and says so). The p95 frame times and title-to-first-frame weren't measured on reference hardware; the browser reaches "ready" in 28 to 60 s on this box (it varies with the load), most of it the 192×192 world generated in wasm.
    7. Met for the no-threads build. tools/heavy.sh tools/web.sh --bundle=B --tour=…/web/walk.tour --reload-tour=…/web/reload.tour --ticks=6000 gives web OK: 22 checks passed. Those checks cover no console or page errors, canvas focus, a drawn 16:9 frame (681 colours), an AudioContext running after the first key, the tour, a clean engine exit, and the save kept across a reload in IndexedDB. The browser's state at tick 115 equals the desktop's. The run found a player bug: quitting with sounds playing threw in the page, so the engine never exited and the save was lost. A finished run now falls silent before it quits. The threaded build was not run for Tideline.
    8. Met. engine/tests/present/shots/game_frames.sh --open round_d draws through the real player. The night's mean luma is 0.016, and a lit lamp raises it 47% (the spec asks 40%). At noon the sentry reads 0.19 against the turf behind it at 0.51. Under a pine whose crown covers the player, 62% of the player's silhouette shows through the stipple. Two of these failed before the pack was tuned (+19% with the old night, 43% with low crowns), so the checks can fail. There is no stored golden set of frames yet.
    9. Met. Every cue the game can emit (19, footsteps per ground included) names a Sound, every loop's seam ratio is 0.46 or less (seamless is about 1 or less), and every bake lands within 1.5 dB of its mix-sheet level (gw_tideline_sound_test.gd). Deleting snd.step_heath makes validate fail with cue.unknown_sound.
    10. Met. tools/check-boundary.sh (in check-all.sh) finds none of the 99 document ids in examples/ (Tideline's and the other games') in the 334 code files of the engine addon, the player, the CLI and the core. A planted &"arch.sentry" in a kit fails it. What Tideline needed from the engine landed as generic features with their own tests: footstep events (kit.move), snake_case builder slots (kit.mesh), routing to a boulder, body-wide paths and kept route fields (kit.world_tiles), a tether to the patrol round (kit.brain_fsm), items at spawn (kit.inventory), the slate's load bar and short key caps (kit.ui), silence before quitting (the player), template manifest defaults (core), {ground} cues over the biome the world draws (core and kit.audio), and InputMap menu actions the monkey doesn't press (kit.core).
  • Fell short: A6's shader check and frame-time budgets (above). A7 on the threaded build. A8's accepted golden set. The sentry's tell reads mostly as its pose; its lens is small at this camera. The world takes 28 to 60 s to generate in the browser. (Since 2026-10-01 generation is about 11x faster and the first chunks about 5x; Tideline's browser start went from about 34 s to 29 s, and most of what is left is baking its sounds.)
  • Change: the brief asks for the slice "entirely through Gamewright". M1 does it through Gamewright's data path with no AI, so that M2 can do it through the Director without also debugging the engine. This mirrors Reelwright, whose hand-written M1 scene became the fixture its AI stages are tested against.

M2 The Director, from Claude Code — landed

Landed (2026-10-01): the tool registry and change store, 28 tools over MCP, stage gates C1/C2, run tools and a VerifyReport on every proposal, slice and stacked proposals, replaces for the Director's own drafts, and tools/director/turn.sh. The acceptance run (docs/demos/m2-acceptance.md): from "a night-coast survival game where broken machines hunt you", a Claude Code Director with only these tools made Nightcoast in nine turns for $12.18. It passes L0–L2 (49 Playtest runs it wrote: a full night, tactics 20/20, trading 0/20, stealth) and the web boot, undo and redo are byte-exact, and the second attack it couldn't express became a KitRequest. L3 was red on two night frames: the sentry's body can't read without light, a real tension between the readability gate and the game's "darkness hides you" pillar. M3 decision 7b settled it: a threat whose body is lost in the dark reads by its lit tell, and both frames read by the sentry's lens, so the pack is green to L3 unchanged.

  • Tool registry, change sets and MCP: gamewright mcp with read, propose, run and decide tools; proposals with base hashes, atomic apply, git commits with a trailer, undo and redo, variation groups, locks by item id; previews as images; verification reports as data.
  • The staged pipeline: brief → template → systems → entities → world → presentation → tuning, with checkpoints C1–C3, per-stage tool sets, and the repair loop.
  • The vocabulary-gap loop: KitRequest documents, and a first local kit built from one.
  • Watch it: in one Claude Code conversation, "a night-coast survival game where broken machines hunt you" becomes a Game Pack that passes L0–L3, from a template, with proposals approved one by one. Then "make the sentry faster and give it a second attack" becomes a proposal with a before/after verification report. Undo works.
  • Acceptance: the directed game passes the same kinds of checks as Tideline's (a proof tour, tactics, stealth ordering, the web boot), written by the Director as Playtest documents.

M3 Verification depth — landed

Design: docs/design/m3-verification.md (bots as input drivers, engine invariants, an in-engine explorer, measured readability, and a planted-bug corpus as the acceptance test).

Landed (2026-09-30): the monkey with per-tick engine invariants and Playtest fuzz runs; the goal-seeking seek bot with reaction time and fumbles; the in-engine explorer (Go-Explore over bit-exact snapshots, a replay for every event it reaches, reachability as a gate); readability measured in frames (colour difference, calibrated on accepted frames); L4, a grounded judge that asks a vision model only what the engine can check (the player's position scored against its pixels; comprehension as advice), off unless asked, cached and budgeted; and L5, every proof tour in Chromium with the desktop's state hash. Then (M3c) text a person can't read: the engine reports every text it draws at a shot, and L3 is red for a line cut short, a wrapped label's dropped lines, text off the frame or under 18 px at 1080 rows, naming the screen, the widget and the text for the Director. Then (M3d) a threat lost in the dark reads by its lit tell: the player measures exactly the pixels that go dark with its glow. Tideline's sentry got a faint glow in its working part, so it can be found from behind. Then (M3e) a Playtest's asserts are checked by the engine where any run ends (sim --asserts), so kit functions (platformer_done, grid_solved, item_count) answer as the game computes them, a bot's asserts count too, and the core's copy of the VM is gone. Then (M3f) text a person can't tell from what is behind it: L3's text_contrast measures the luminance ratio across each text's ink and is red under 3:1, calibrated on every sample game's accepted frames (the faintest whole text stands 5.4:1). Then (M3g) a platformer is played as a person would play it, not only by its witness: a playthrough bot with reaction time, imprecise jumps and fumbles at four skills measures hurts, deaths and time per level, every platformer gets a casual Playtest that fails when most runs give up, and a planted level the witness finishes and a person can't is red at L2. Then (M3h) every action survival game is fuzzed and played by a newcomer without anyone writing a Playtest: the template ships test.fuzz (the monkey on 4 seeds, every invariant kept) and test.first_minute (seek makes the first thing the game lets it make and holds a minute; most runs must not be lost in it), calibrated green on Tideline and Nightcoast over 20 seeds each, and a planted sentry at the player's spawn is red at L2 on it alone. Then (M3i) a Screen that doesn't fit a phone: L3 draws every tour that shows text a second time as an upright phone shows it, beside the game's own touch controls, and is red for text cut, over other text, under a pane or under 11 pt there (phone_text_fits, phone_text_size), with the same rules the deploy's phone visit uses, which judge a monitor's text over text or under a pane too (text_fits), and the Director's preview draws a phone on asking (phone: true). A label that fits a monitor and is cut on a phone is red in the Director's own checks, on every Screen the game has: L3 opens each app and title no tour shot, and preview opens any by id (screen). On a phone, a hint names the button to tap (OK, Back, ↑↓), not a key. Thirteen planted bugs each go red at their rung and not before.

  • The template heuristic agent with human-like noise, the monkey agent, and an explorer search (Go-Explore style) for templates whose state snapshots cleanly.
  • Trace metrics: the §5.1 gates of research/testing-verification.md, with the fun-ish signals as warnings until calibrated.
  • L4 judge: grounded readability ("point to the player"), first-minute comprehension, pairwise style checks.
  • L5 web: the golden path runs in the browser and its outcome is compared with native.
  • Acceptance scenarios are re-run automatically on every proposal.
  • Watch it: gamewright verify <pack> prints a ladder report with frames and metrics, and a planted bug (an unreachable key, a softlock, an invisible enemy) is caught at the right rung.

M4 "Any game": two more templates — landed

Landed: puzzle_grid: kit.grid and kit.grid_rules (PuzzleScript-style rules as data, shared vectors in both languages), a solver that proves every level solvable at bake and stores the witness a tour replays, and a sample game passing verify. platformer_2d: kit.platformer (a kinematic mover shared with the core through vectors), a jump-aware reachability search that stores each level's witness, the rooms.chain generator pass, and kit.sprite's sprite baker (any Model recipe to sheets, the same pixels headless and on the web). The genre needed two new kits. Then the Director made one of each from a prompt (docs/demos/m4-director.md): Lamplighter, a lighthouse Sokoban, in six turns for $10.55, and Acorn Rooftops, a fox platformer with pixel-art sprites, in four turns for about $8. Neither needed a new kit. Their reports led to the fixes they asked for: a server that answers in time, solves remembered, views that say which palette slots they read (and a grid sky), and two in flight (sprites out of play state, previews of any level).

  • puzzle_grid (turn-based rules, undo, a solver that generates levels with witnesses) and platformer_2d (a kinematic mover, jump-aware reachability, room chains).
  • The sprite baker: any 3D recipe rendered from fixed ortho angles into sprite sheets, which is how 2D templates get consistent art.
  • Watch it: the Director makes a Sokoban-like and a small platformer from prompts. Count how many new kits each needed; the goal for the next template is "mostly packs".

Landed: the play origin at gamewright-play.vercel.app (its own site: vercel.app is on the Public Suffix List), tools/play-origin/deploy.sh with the web rung against the live URL, and gamewright.diy/play with seven games, three of them made by the Director (Nightcoast, Lamplighter, Acorn Rooftops), each proven live in Chromium with the desktop's state hash. Every game opens on its name and keeps a loading screen up from the click until it can be played: the step the engine is on, then its shader warm-up counted one program a frame over the game's own title screen; the harness fails a visit whose screen drops early. Every game plays on a phone too, with touch controls made from its own InputMap, proven upright and sideways, and has its own page (/play/<slug>) with a link preview, so one game can be shared. Starts got shorter: world generation runs about 11x faster with the same worlds, and sounds bake after the start, a share of each frame, so Tideline is playable 7 s after the click in the browser check (was 43) and Nightcoast 5 (was 18). On a phone a game's text grows to at least 11 points on the person's screen however small its frame is shown, and every deploy proves each game on a phone, upright and sideways. A game can be played again from its end: every ending of every game shows a card that says what happened and which key plays again. Still to do: Blob storage once people make games.

  • The play origin (play/, its own domain), the shared no-threads player, bundles in Vercel Blob, a gallery of the sample games with posters and tap-to-play, and the web ladder rung in CI against the live URL.
  • Play it: Tideline and the M4 games in a browser, from the site.

M6 Presentation depth — started

Landed: the restyle gate. A look-only proposal is verified against its base and goes red (restyle.changed_play) if any state hash differs, and a lint keeps simulation code from reading what only views read. Music: the Score kind and kit.music render each stem from a seed to an exact whole-bar loop, voiced by the game's own Sounds, layered by pure expressions over the game (tension, the hour) and switched on bar lines; a probe measured that the web build's Sample mode plays only WAVs, so every stem is a looping WAV started with its section in one frame. Then (M6c) a Style names its score, so a restyle swaps the music; turning on a kit that only draws counts as presentation; Tideline has a score; and music bakes in steps a frame can afford, its first section starting once its lead stem is ready. Then a look stays out of play's state (components a kit marks as presentation, like sprites and poses, leave entity rows, saves and hashes, so a sprite-only change passes the restyle gate), and kit.audio's sounds bake in passes in the order they are heard, so a game draws before it sounds. Then sprites move: a Model says in data how its thing moves (joints on mesh.parts, poses as keyed moves), a Sprite's clips sample those poses, and a view picks clip and frame from the body's state alone, so the Director's fox gallops and its crows strut, with no state hash moved. Then motion presets: body plans in the library (biped, quadruped, bird) name the roles a body's joints play and offer gaits and poses as those same moves (walk, trot, gallop, hop, strut, flap, jump, fall, hurt), so a Model takes a gallop by name and changes what it wants; the fox, the crow and the hero now take theirs, and a hare drawn from parts hops with no key of its own. Still to come: buildings, and tiles.

  • The music sequencer (score spec → exact-bar stems → synchronized and interactive streams, tested in web sample mode first), a building grammar, figure rigs with procedural gait, and procedural tiles and UI themes.
  • Restyle end to end: one style swap re-looks a game, and the ladder proves the state hashes didn't change.

M11 Gamewright Studio, for macOS, Windows and Linux — in progress

First priority (2026-10-02). Gamewright is first a desktop studio for building games with this engine, installed from gamewright.diy on macOS, Windows and Linux; the web comes second. The studio is a Godot app, built in Godot the way Godot's own editor is, and the game being made plays inside it on the same engine. The gallery shows what it makes; the studio is the product. This milestone comes before M7–M9 and takes over M8's Director-in-a-UI and M9's desktop downloads.

  • Projects: a new game from any template, or open one; every change versioned, undo always.
  • The Director in the app: say what you want; it works with the same tools it has today and answers with proposals you can read (what changes, a before and after, what the checks say) and approve, adjust or undo. The person decides; the Director never writes past them.
  • Play while you make it: the game rebuilds on each approved change and plays in the studio, from any level or place, or in a window of its own.
  • Checks as you go: the ladder's results beside the game: Playtests and bots, frames on a monitor and a phone, text that is cut or crossed, the browser on the desktop's state.
  • Documents and assets: every document browsable and editable through forms built from the schemas, so nothing invalid can be saved; models, sprites and sounds previewed as they build.
  • Export and publish: a game built for desktop and the web, and published to the gallery.
  • Packaged for each system, signed once the owner has the accounts (an Apple Developer account, a Windows signing service), with updates. Architecture and its risks: research/studio-architecture.md.
  • The plan (approved 2026-10-03): design/m11-studio.md. Six steps, each ending in something watched: the player hosted inside another app, the core free of the repo, the Studio opening and playing a game, the Director in it, new games and export, installers for three systems.
  • Watch it: install the studio, start from a template, ask the Director for a game, play it, approve a change, see the checks, export it.
  • Where it stands (2026-10-06, 0.2.0): the second layout (design/studio-layout.md: the project, the game in the middle, the Director and Inspector in a dock, a console and a status bar, menus in the Mac's menu bar), export for every system, levels painted on a canvas (design/studio-level-editor.md), stacked proposals approved together, and the game drawn at a Retina screen's pixels. The web Studio's client and host are on main (design/web-studio.md); it goes live once its host is deployed. Still to come: signing, previews of models and sounds as they build, and publishing to the gallery from the Studio.

M12 Runners: the web Studio's work on your own computer — started

The web Studio's games, builds, playtests and Director run on a computer of the person's own, and the host becomes a front door that signs people in and relays (design/m12-runner.md, adapted from Reelwright's M15). Mode b first: gamewright runner --games DIR offers that computer's games, paired once with a code from Your computers. Then Director turns on the owner's Claude plan, a Computers panel in both Studios, and jobs for games kept on the host if mode b is not enough.

  • Watch it: pair this computer, open one of its games at gamewright.diy/app, play and playtest it there while its Godot runs here; turn the runner off and see the game say so.

M7 Tier 2 adapters

  • Image (gpt-image-2.5 hosted, FLUX.2 klein 4B open), PixelLab tilesets, ElevenLabs SFX, ACE-Step music; 3D last. The generate → freeze → normalize → QA → approve pipeline with provenance and licence validation.

M8 The Director on the web

  • A web studio with chat, a live preview iframe on the play origin, proposal review and approval, bring your own key, and a hosted MCP endpoint. Invite-gated, with a daily quota and a spend ledger.

M9 Accounts, projects and community

The web Studio behind sign-in came first, with M11: the same Studio in the browser at gamewright.diy/app, on a host of its own with invite-only accounts and a code sent by email (ADR-0013, docs/design/web-studio.md). What is left opens it up:

  • Sign-up for anyone, Better Auth + Neon, projects with version history, drafts and published games, remix, moderation and reporting. (Desktop downloads moved to M11, the studio, first.)

M10 More templates and kits — started

Landed (M10a, 2026-10-01): visual_novel, the fourth template, with no new simulation kit: a story is a Dialogue (the L2 graph ADR-0003 names) that kit.core runs beside its RuleSets, flags are vars, and the look is one kit.ui Screen with baked figures, filled backdrops, words that appear as they are said and the game's own choice list. The thesis test and the count are in docs/design/m4-templates.md. Its sample, examples/fog_signal, is in the gallery: four endings, every reading proven by Playtests, L3 green, the browser on the desktop's state.

Landed (M10b, 2026-10-02): adventure, the fifth template: a village with people to talk to, a quest given in words, a wild place with things that hunt you, items to find and use, and the way back. No new kit and no new kind. Saying the genre with the vocabulary found six gaps; five were closed with small generic features, each tested and each counted in the design: kit.harvest's usables (the use key talks to a person or reads a sign, starts their Dialogue, and owns the key and the body until the talk is over), kit.core's seek talk goal (with goals that may repeat and a read_all verb), kit.ui asking for a talk's keys on a phone, and kit.world_tiles rules kept to a disc of the map (a village green, a wood at one end, a trail). The sixth, using up a carried item later, closed the same day (docs/design/item-use.md): an Item's use (verb, charges) says what using it costs, the carry app's confirm uses it (kit.inventory takes one when its charges are spent and sends inventory.used), and a rule says what it does. Thornwick's berries are carried and eaten from the pack when hurt; the seek bot eats with use:item.berries after its first fight. The template carries test.fuzz, test.first_talk and test.quest, and plays its own quest to a win. Its sample, examples/thornwick, is a bell fetched home from Briar Wood: four people to talk to, a hatchet, three thornbacks, music, about five to eight minutes (an estimate). L0–L3 green (the seek bot plays the quest on 4 seeds, two fights each, never downed; 14 frames all readable), the proof tour in Chromium on the desktop's state, a phone plays it by touch, and it plays in the gallery (live 2026-10-02, the eighth game).

Landed (M10c, 2026-10-02; not yet deployed): twin_stick, the sixth template: one stick moves, the other aims and shoots, waves of foes come through the gates, the score grows as you survive, and a short run ends in a win or a loss. Saying it with the vocabulary found seven gaps. One was a new mechanic, and it is the one new simulation kit: kit.ranged, shots that fly (each an entity of a projectile Archetype, stopped by walls, their range or the first body they touch) and land through kit.melee's own rules (a dodge lets them pass, plate turns them; a state machine's shoot gives a foe a tell and an aim fixed when it begins). The rest are small generic features, each tested and counted in the design: the touch layer's second stick (both thumbs at once), a key hint that names a stick (WASD, ↑←↓→), the monkey pushing an aim stick, the skirmish bot (an L2 player that aims, leads, strafes and dashes), and routing a swarm cheaply (a lazily flooded route field, exact; kit.move's opt-in rerouteMs), which took a twin-stick's sim from 14 ms a tick to 4 or 5. Playing again after a loss closed in the player app (GwPlayAgain). Every gallery proof tour ends on its old state hash. The template carries test.fuzz, test.first_wave and test.run, and wins its own five waves. Its sample, examples/saltwell, is a well held through one desert afternoon: scuttlers, spitters that spit from a distance, ramhorns armoured in front, six waves, music. L0–L3 green (the skirmish bot wins the run on all 4 seeds; 8 frames and 8 on a phone all readable), the proof tour in Chromium on the desktop's state, and a phone plays it with a stick under each thumb. It is in tools/play-origin/deploy.sh's list for the next deploy.

  • Visual novel, top-down adventure and twin-stick (landed), then roguelike and tower defense, each mostly packs. Kits grow from logged KitRequests. A local-kit promotion workflow turns the owner's local kits into reviewed engine kits.

From docs/ROADMAP.md in the Gamewright repository.