Lists what a game package requires and how to validate it, matching the checks journal check performs.
5.7 KiB
name, description
| name | description |
|---|---|
| game-prep | Prepare or validate a game package under games/ for this solo journaling workspace. Use when adding a new game system, porting one from games/generic/, reviewing whether a game package is complete, or checking that its rules, tables, character backgrounds, and commands are wired up correctly before starting a campaign. |
Preparing a game package
A game package is a directory under games/<id>/ that holds everything true
about a game before play starts: its rules, spark tables, character options,
and tool scripts. Campaigns own the play state and reference a game by id from
campaigns/<name>/campaign.md frontmatter (game: <id>).
Read docs/games.md for the full contract. games/generic/ is the reference
implementation — copy it as a starting point.
Rule of thumb: a game is what is true before play, a campaign is what play changes. Never copy game content into a campaign; reference it.
Required contents
| Path | Required | Purpose |
|---|---|---|
package.json |
yes | @solo/game-<id>, "type": "module", main/exports; depend on @solo/oracle if scripts use dice or tables |
index.js |
yes | default-export manifest: id, title, description, rules, commands |
game.md |
yes | authoritative rules the agent reads each session |
tables/*.csv |
yes | spark and complication tables, header min,max,text[,tags] |
characters/ |
yes | backgrounds, playbooks, starting options — the character options, not the PC |
rules/ |
recommended | longer rulebook chapters, read on demand |
scripts/ |
optional | standalone tool scripts for one-off jobs |
Details that trip people up:
- The directory name is the game id. Keep the manifest's
idand the package name@solo/game-<id>in sync with it. - Ship a
complication-themes.csv.journal oracle --complicateresolves that table name, and without it on either the campaign or the game the roll fails. There is no cross-game fallback. - Tables must be contiguous and non-overlapping.
min/maxare inclusive integers and define the die range; every integer in the table's span should be covered exactly once. Quote anytextcontaining a comma. - Commands are declared in
index.jsascommands: { name: { description, run } }and exposed asjournal <name>. Handlers receive(args, ctx)whereargsis{ positional, flags }andctxcarriesfindTableplus the shared helpers. - Run
pnpm installafter adding the@solo/oracledependency or creating a new package, so the workspace symlink exists.
Preparation workflow
- Copy the reference:
games/generic/→games/<id>/. - Edit
package.json: setnameto@solo/game-<id>and a real description. - Edit
index.js: setid,title,description; replace or remove the example command. - Write
game.md: resolution, stats, tracks and conditions, character creation, and the tables the game provides. - Add tables to
tables/, one CSV per table, ranges contiguous. - Add character options to
characters/— rollable ones as CSV, prose as markdown. - Add
rules/chapters for anything too long forgame.md. - Add tooling: preferred path is a
commandsentry inindex.jsfor anything the agent calls during play; standalone one-off scripts go inscripts/. pnpm install.- Validate (below) before starting a campaign.
Validation
Run all of these. Each proves something the others do not.
| Command | Proves |
|---|---|
pnpm install |
the @solo/oracle workspace link resolves |
pnpm journal check --game <id> |
package.json parses and is named right, index.js loads, the rules file exists, tables parse and are contiguous, tables/ and characters/ exist |
pnpm journal games |
the game appears in the catalog; a manifest that throws shows as ERROR: |
pnpm journal game <id> |
rules path, table count, characters path, and the command list all resolve |
pnpm journal roll <table> --game <id> |
each table rolls and its range resolves |
pnpm journal <command> --game <id> |
each game command runs |
journal check exits non-zero on errors. It reports:
- errors — overlapping table ranges, CSV parse failures, invalid or missing
package.json, missing game. - warnings — range gaps, package name mismatch, missing
"type": "module", missingindex.js/tables//characters/, missing rules file.
Fix every error, then work the warnings down to zero. The checks live in
packages/cli/src/cli.js (checkGamePackage, checkTablesDir).
Definition of done
games/<id>/exists; directory name, manifestid, and package name agree.pnpm journal check --game <id>exits 0 with no errors.pnpm journal gameslists it withoutERROR.pnpm journal game <id>shows the rules path and every intended command.- Every table rolls cleanly and its ranges are contiguous.
game.mdcovers resolution, stats, tracks, character creation, and the game's tables.characters/holds the character options.- A complication table is present if the game uses
--complicate. pnpm journal new-campaign scratch --game <id>succeeds (then remove the scratch campaign).
Common failures
- Overlapping ranges — e.g. rows
1-3and3-6both cover 3. Error. - Gaps — e.g. rows
1-2and4-6leave 3 uncovered. Warning. - Unquoted comma in a table's
textshifts the columns; wrap it in quotes. ERR_MODULE_NOT_FOUND: @solo/oracle— the dependency was added butpnpm installwas not run.- Manifest id drifting from the directory name —
journal game <id>still works (the directory wins), but the package is inconsistent and the docs become misleading.