harvest-game
Installation
SKILL.md
The harvest-game loop
Build a game, harvest the engine gaps it exposes. Take the invocation argument and resolve a target game:
- A specific game named → that's the target. Research it.
- A link (repo or game page) → that's the target, and the link is its spec. Read it for mechanics, systems, camera, controls, and content scope — it is a research source, never a port source. Build fresh from the engine surface; translating its code line-by-line faithfully recreates its workarounds and hides exactly the gaps this loop exists to expose.
- A genre → pick a well-known game in that genre whose core mechanics stress engine areas no existing
Games/*game already covers. - Nothing / "find one" → web-research currently popular or recently viral games and pick one the engine can't obviously do yet. Prefer games whose defining mechanic looks missing from the engine surface.
Then run the whole loop in this session:
- Research. Web-search the target's core loop, mechanics, camera, controls, win conditions, and HUD until you can describe a minimal playable slice. Keep the game profile in your working notes only — the game's name and genre must never appear in the filed issue or any committed text other than the game's own directory.
- Work on your session's branch, per the root workflow — the PR comes later, when the game is real.
- Build a minimal playable version in
Games/<id>— core loop playable, not a full clone. Minimal never means graybox: the slice carries the target's identity — a named aesthetic with a committed palette (ground, sky, UI panel/ink/accent hex values), UI copy in the fantasy's own voice, and an initial camera framing that shows the game at its best — because presentation is where a whole class of engine gaps lives (sky/backdrop, time-of-day lighting, palette seams, camera pose) and none of them surface on a gray plane. Give the slice a timed observable acceptance up front ("run untouched at max speed for five minutes: what does a player actually see?") and judge the final screenshot against it. Wire it as the otherGames/*do: a private workspace package@games/<id>with./srcexports and no build, plus the standalone dev harnesscheck-game-shapeenforces (rootindex.html+vite.config.ts,src/index.css, a"dev": "vite"script). Games auto-register fromGames/*inapps/dev's registry and the jgengine.com Games dropdown — no registry entry, vite alias, or@gamesdependency to add by hand. Follow thejgengine-newgameskill for the build phases and build from the engine surface in thejgengine-apiskill, not by copying other games. - Track gaps the moment you hit them in your working notes — one raw engine problem per line, engine terms only, no game context, no solutions. The bar is not "the engine couldn't do it" — friction is a gap too: anything the game had to hand-roll that should be a natural engine primitive or one-liner. Tag each line
blocker(no engine-surface route existed),workaround(a route existed but the game had to hand-roll something the engine should own), orergonomics(it worked but took boilerplate a primitive would erase). A gap you hit while building outranks a gap you suspect from reading; note both, but only after genuinely attempting the engine-surface route. - Verify per the
jgengine-verifyladder — cheapest gate first, browser last:bun run check-types, thenbun test packages Gamesincluding the co-located<game>.world.test.tssummarizeEnvironmentassertions for everyenvironment()world (this is the scene-correctness gate, not the screenshot), thenbun run shoot <id> --mode uiand--mode playas the final human glance — open the PNGs and actually look at them. A hung shot is never re-run in the foreground; the world test is what proves the scene resolved. - Session end. File the gaps as
[FEATURE]issue(s) on this repo — title[FEATURE] <brief summary>, body a numbered list of the raw engine problems, each carrying itsblocker/workaround/ergonomicstag (nothing else, no game context, no solutions). Then ship per CLAUDE.md's ship rule: push, open the PR (GitHub MCPcreate_pull_request),subscribe_pr_activity, squash-merge immediately (merge_pull_request, or queueenable_pr_auto_merge(squash) if checks block it), then verify green with the 60-second worker check per CLAUDE.md's ship rule (nosend_latercheck-ins).
Finish by reporting: what was built and where, the issue link(s), and how many gaps were filed.