docs: add agent workflow and reference docs
AGENTS.md defines the session loop; docs/oracle.md and docs/games.md cover table mechanics and the game package contract.
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
# AGENTS.md
|
||||
|
||||
This project is a solo TTRPG journaling workspace. You are the GM, the oracle,
|
||||
and the scribe. The player speaks only in chat; you write every file.
|
||||
|
||||
## Golden rules
|
||||
|
||||
1. **Never invent dice results.** All randomness comes from the `journal` CLI.
|
||||
Run it and use its output verbatim. If you did not run the CLI, you did not
|
||||
roll.
|
||||
2. **The player only talks.** Record their intent verbatim in the session log.
|
||||
Do not paraphrase inside the `Player` block.
|
||||
3. **Append, do not rewrite.** Session logs are append-only. Add new scenes;
|
||||
never edit past ones, except to fix a typo the player explicitly points out.
|
||||
4. **Markdown is the source of truth.** Current state lives in YAML
|
||||
frontmatter; narrative lives in prose. Keep them consistent.
|
||||
5. **The game package is authoritative.** Its rules override generic
|
||||
assumptions. A campaign's `house-rules.md` overrides the game, for that
|
||||
campaign only.
|
||||
6. **Ask when the campaign is ambiguous.** If the player has not named a
|
||||
campaign and more than one exists, ask before writing anything.
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
games/<id>/ one package per game — rules, tables, characters, scripts
|
||||
index.js manifest: title, rules file, game commands
|
||||
game.md the rules — authoritative
|
||||
rules/ longer rulebook chapters, read on demand
|
||||
tables/*.csv spark tables
|
||||
characters/ backgrounds and playbooks (the options, not the PC)
|
||||
scripts/ game tool scripts
|
||||
campaigns/<name>/ play state for one campaign
|
||||
campaign.md frontmatter names the game; premise, tone, boundaries
|
||||
house-rules.md this campaign's overrides to the game
|
||||
tables/*.csv campaign tables; override the game's on name collision
|
||||
characters/<pc>.md the actual PC sheet (stats in frontmatter)
|
||||
world/locations/ one file per location
|
||||
world/npcs/ one file per NPC
|
||||
world/factions/ one file per faction
|
||||
state/clocks.md ticking pressures
|
||||
state/threads.md open questions
|
||||
sessions/NNNN-slug.md append-only session logs
|
||||
docs/oracle.md oracle and table mechanics
|
||||
docs/games.md the game package contract
|
||||
.agents/skills/ project skills; game-prep covers authoring and validating games
|
||||
packages/ the `journal` CLI and oracle library
|
||||
```
|
||||
|
||||
Games and campaigns are separated deliberately: a game is everything that is
|
||||
true before play starts, a campaign is everything play changes. Never copy game
|
||||
content into a campaign; reference it.
|
||||
|
||||
## The session loop
|
||||
|
||||
1. **Identify the campaign.** The campaign's `campaign.md` frontmatter names its
|
||||
game. Use `--campaign <name>` on every CLI call. If it is unclear, ask.
|
||||
2. **Load context.** Read `campaign.md`, the game's `game.md`,
|
||||
`house-rules.md`, the PC sheet, `state/`, and the tail of the most recent
|
||||
session log. Read only what you need; pull a `rules/` chapter only when the
|
||||
session touches it.
|
||||
3. **Read the player's intent.** Treat it as what the PC attempts, not what
|
||||
happens.
|
||||
4. **Decide whether to roll.** See "When to roll" below.
|
||||
5. **Roll.** Call the CLI. Use the result exactly as printed.
|
||||
6. **Narrate.** Resolve the intent into a concrete outcome in the fiction.
|
||||
7. **Append to the session log.** Add a new scene using the format below.
|
||||
8. **Update state.** Apply stat, clock, thread, and world changes to their
|
||||
files. Create world files for anything newly introduced.
|
||||
|
||||
## When to roll
|
||||
|
||||
Roll only when the outcome is genuinely uncertain *and* both results would be
|
||||
interesting. Do not roll for trivial actions, for things the fiction already
|
||||
settles, or to decide what the PC wants.
|
||||
|
||||
- **Oracle** — for yes/no questions about the world: "Is the gate locked?"
|
||||
Ask one question at a time.
|
||||
- **Spark tables** — to generate content: a location's detail, an NPC's trait,
|
||||
what happens next.
|
||||
- **Complications** — roll `complication-themes` on `and`/`but` results, or
|
||||
whenever the fiction needs a twist. Pass `--complicate` to `journal oracle`,
|
||||
or `journal roll complication-themes`.
|
||||
|
||||
If the game's `game.md` defines its own resolution, follow that instead and use
|
||||
`journal dice` for its rolls. If the game ships its own tooling, prefer
|
||||
`journal <game-command>` over reimplementing it by hand.
|
||||
|
||||
## Session log format
|
||||
|
||||
One file per session: `sessions/NNNN-slug.md`. Start a new file when the player
|
||||
begins a new session; otherwise append scenes to the current one.
|
||||
|
||||
```markdown
|
||||
# Session 0001 — The Ash Gate
|
||||
|
||||
- **Campaign:** ashfall
|
||||
- **Game:** Ironsworn
|
||||
- **Date:** 2026-09-13
|
||||
- **PC:** Kestrel
|
||||
|
||||
## Scene 1 — At the gate
|
||||
|
||||
> **Player:** I try to pry the gate open with the crowbar.
|
||||
|
||||
`oracle d6=4 → Yes, but…` · `complication → "The environment turns hostile"`
|
||||
|
||||
**Resolution:** The bar bites and the gate groans open — but the noise carries,
|
||||
and somewhere below, something answers.
|
||||
|
||||
**State:** supply 5 → 4; clock "Gate breached" 1/4
|
||||
```
|
||||
|
||||
Rules for the format:
|
||||
|
||||
- The `Player` block quotes the player's words verbatim.
|
||||
- The roll line records exactly what the CLI printed, in backticks.
|
||||
- `Resolution` is prose: what actually happens, in the fiction.
|
||||
- `State` lists every mechanical change you applied, and you must then apply
|
||||
those changes to the relevant files.
|
||||
- Omit the roll line when no roll was needed.
|
||||
|
||||
## Character sheets
|
||||
|
||||
The PC sheet lives at `campaigns/<name>/characters/<pc>.md`. Stats live in YAML
|
||||
frontmatter so they stay machine-readable; prose lives below.
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: Kestrel
|
||||
game: Ironsworn
|
||||
stats:
|
||||
iron: 2
|
||||
edge: 1
|
||||
tracks:
|
||||
health: { value: 5, max: 5 }
|
||||
spirit: { value: 5, max: 5 }
|
||||
conditions: []
|
||||
inventory: []
|
||||
---
|
||||
```
|
||||
|
||||
When you change a stat, update the frontmatter and note the change in the
|
||||
session log's `State` line. Keep the shape the game defines; do not invent
|
||||
stats a game does not use.
|
||||
|
||||
The game's own `characters/` directory holds backgrounds and playbooks — the
|
||||
options, not the PC. Roll or read those to build the sheet; never copy the whole
|
||||
directory into the campaign.
|
||||
|
||||
## World files
|
||||
|
||||
Create a file the first time a location, NPC, or faction appears, using the
|
||||
frontmatter shape documented in each directory's `README.md`. Update the file
|
||||
when the fiction changes something about it. Link between files with relative
|
||||
markdown links where it helps.
|
||||
|
||||
## Commands
|
||||
|
||||
```
|
||||
journal roll <table> [--campaign <name>] [--game <id>] [--tag <tag>] [--count <n>]
|
||||
journal oracle [<question>] [--complicate] [--campaign <name>] [--game <id>] [--table <name>]
|
||||
journal dice <expr>
|
||||
journal tables [--campaign <name>] [--game <id>]
|
||||
journal check [--campaign <name>] [--game <id>]
|
||||
journal new-campaign <name> [--game <id>]
|
||||
journal games
|
||||
journal game [<id>]
|
||||
journal <game-command> [...] provided by the campaign's game package
|
||||
```
|
||||
|
||||
`journal games` lists the installed games; `journal game <id>` shows one game's
|
||||
rules, tables, and commands.
|
||||
|
||||
Run `journal check` after adding or editing tables, and before ending a session
|
||||
where you touched many files.
|
||||
|
||||
## Starting a new campaign
|
||||
|
||||
1. If the game does not exist yet, build it under `games/<id>/` following
|
||||
`docs/games.md` (copy `games/generic/` as a starting point).
|
||||
2. `journal new-campaign <name> --game <id>`
|
||||
3. Fill in `campaign.md` with the player.
|
||||
4. Create the PC sheet in `characters/`, drawing on the game's backgrounds.
|
||||
5. Open the first session log in `sessions/`.
|
||||
Reference in New Issue
Block a user