diff --git a/AGENTS.md b/AGENTS.md index fb84286..8a97cce 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,16 +8,23 @@ and the scribe. The player speaks only in chat; you write every file. 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. +2. **Never invent facts.** Establish a detail with the oracle, a spark table, or + the files. Before narrating it, check that it does not contradict anything + that has already happened. +3. **Separate truth from perception.** `world/`, `gm/`, and the state files hold + what is *true*. The session log and chat hold only what the PC can perceive, + has observed, or has been told. Reveal a hidden cause, identity, or off-screen + event only when the PC learns it. +4. **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; +5. **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 +6. **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 +7. **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 +8. **Ask when the campaign is ambiguous.** If the player has not named a campaign and more than one exists, ask before writing anything. ## Layout @@ -38,9 +45,11 @@ campaigns// play state for one campaign world/locations/ one file per location world/npcs/ one file per NPC world/factions/ one file per faction + state/knowledge.md what the PC knows, believes, and has not learned state/clocks.md ticking pressures state/threads.md open questions - sessions/NNNN-slug.md append-only session logs + gm/ hidden truth — never player-facing + sessions/NNNN-slug.md append-only, perception-level session logs docs/oracle.md oracle and table mechanics docs/games.md the game package contract .agents/skills/ project skills; game-prep authors games, run-session plays them @@ -51,22 +60,38 @@ 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. +Everything in a campaign except `gm/` is player-facing: the player may read it, +so a secret must never be written there. `gm/` holds the truth the PC has not +learned; `state/knowledge.md` holds the PC's current, possibly mistaken, +picture of the world. + ## The session loop 1. **Identify the campaign.** The campaign's `campaign.md` frontmatter names its game. Use `--campaign ` 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 + `house-rules.md`, the PC sheet, `state/` (including `knowledge.md`), the + relevant `world/` files and `gm/` notes, 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. +6. **Check consistency.** Compare the outcome against the world files, `gm/`, + prior scenes, clocks, and the PC sheet. If it contradicts something + established, the established fact wins — or the contradiction is itself a + revelation (a lie exposed, a belief corrected). Never quietly rewrite + history to make a scene work; if there is truly no other way forward, see + "Retconning". +7. **Narrate what the PC perceives.** Filter the outcome through the PC's + senses, position, and what `knowledge.md` says they know. Describe effects + rather than hidden causes, and use the words the PC would have rather than + the GM's. +8. **Append to the session log.** Add a new scene using the format below. +9. **Update state.** Apply stat, clock, thread, and world changes to their + files. Record what the PC learned in `state/knowledge.md`, and put anything + newly true but not yet perceived in `gm/`. ## When to roll @@ -115,7 +140,9 @@ 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. +- `Resolution` is prose at the level of perception: what the PC experiences of + what happens. Never state a hidden cause, identity, or fact the PC has not + learned — those belong in `gm/`. - `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. @@ -148,12 +175,47 @@ 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 +## Knowledge and secrets + +Two places keep the line between what is true and what the PC knows: + +- `state/knowledge.md` — the PC's working picture: facts learned, beliefs held + (including mistaken ones), and questions still open. Update it whenever a + scene reveals or overturns something. This is what narration may draw on. +- `gm/` — the truth the PC has not learned: hidden motives, unrevealed + identities, off-screen events. Never player-facing. Write here when you + establish something true that the PC has not perceived. + +Before narrating, check the outcome against both. A fact in `gm/` must not +surface in the log or in chat until the PC observes it or is told. + +## Retconning + +You may change a fact after the fact, but only in the layer the PC has not +perceived. The test is perception: if every session-log entry and everything in +`state/knowledge.md` still reads exactly as before, the retcon is invisible and +allowed. What the PC saw, heard, or was told stays fixed; the cause behind it +may change. + +Use it to repair a plot that cannot otherwise be made to work — a contradiction +with no way forward, a dead end you created. Do not use it liberally, and never +to dodge a consequence the fiction already earned. Prefer writing forward, or +revealing that a belief was wrong, before reaching for this. + +Record each retcon in `gm/retcons.md`: what changed, and why. + +## Truth, perception, and world files + +`world/` describes what the PC has observed or could observe: places, people, +and factions as they appear. It is player-facing. A hidden motive, an unrevealed +identity, or an off-screen plan belongs in `gm/`, not here. 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. +when the fiction changes something about it — and when the PC learns that an +earlier impression was wrong, record the correction in `state/knowledge.md` +rather than editing history. Link between files with relative markdown links +where it helps. ## Commands diff --git a/campaigns/_template/gm/README.md b/campaigns/_template/gm/README.md new file mode 100644 index 0000000..cf40723 --- /dev/null +++ b/campaigns/_template/gm/README.md @@ -0,0 +1,24 @@ +# GM only + +Truth the PC has not learned: hidden motives, unrevealed identities, off-screen +events, and what is really going on. + +**Not player-facing.** The player may read anything else in the campaign, so a +secret must never be written outside `gm/`. Nothing here may appear in a session +log or in chat until the PC observes it or is told. + +Keep `../state/knowledge.md` as the PC's counterpart: what they know, believe, +and suspect. When the two disagree, `knowledge.md` is what the PC currently +thinks — narrate from it, not from here. + +## Retconning + +You may change a fact here after the fact, but only in the layer the PC has not +perceived. The test is perception: if every session-log entry and everything in +`state/knowledge.md` still reads exactly as before, the retcon is invisible and +allowed. What the PC saw, heard, or was told stays fixed; the cause behind it +may change. + +Use it to repair a plot that cannot otherwise be made to work. Do not use it +liberally, and never to dodge a consequence the fiction already earned. Record +each one in `retcons.md`. diff --git a/campaigns/_template/gm/retcons.md b/campaigns/_template/gm/retcons.md new file mode 100644 index 0000000..1310188 --- /dev/null +++ b/campaigns/_template/gm/retcons.md @@ -0,0 +1,12 @@ +# Retcons + +A log of facts changed after the fact. Each entry records what changed and why, +so the change is not quietly contradicted later. + +A retcon is only allowed in the layer the PC has not perceived: every session +log entry and every line of `../state/knowledge.md` must still read exactly as +before. See `README.md`. + +| Session | What changed | Why | +|---------|--------------|-----| +| | | | diff --git a/campaigns/_template/state/knowledge.md b/campaigns/_template/state/knowledge.md new file mode 100644 index 0000000..cd30f63 --- /dev/null +++ b/campaigns/_template/state/knowledge.md @@ -0,0 +1,31 @@ +# What the PC knows + +The PC's working picture of the world — not the world itself. Narration may draw +on these entries and on what the PC perceives now; anything the PC has not +learned belongs in `../gm/`. + +Update this file whenever a scene reveals something, confirms a suspicion, or +overturns a belief. A mistaken belief stays here under Suspected until the PC +learns better, even after the GM knows the truth. + +## Known + +Facts the PC has learned or observed, and where they learned them. + +| Fact | Learned | +|------|---------| +| | | + +## Suspected + +Things the PC believes but has not confirmed — including beliefs that are wrong. + +| Belief | Basis | +|--------|-------| +| | | + +## Open questions + +Questions the PC is actively trying to answer. + +- diff --git a/campaigns/_template/world/factions/README.md b/campaigns/_template/world/factions/README.md index a46368f..db756e3 100644 --- a/campaigns/_template/world/factions/README.md +++ b/campaigns/_template/world/factions/README.md @@ -2,6 +2,9 @@ One file per faction, named `kebab-case.md`. +These files are player-facing: record what the PC has observed or been told. A +hidden agenda or an off-screen plan belongs in `../../gm/`. + ```markdown --- name: diff --git a/campaigns/_template/world/locations/README.md b/campaigns/_template/world/locations/README.md index 4610384..eee0fa6 100644 --- a/campaigns/_template/world/locations/README.md +++ b/campaigns/_template/world/locations/README.md @@ -3,6 +3,9 @@ One file per location, named `kebab-case.md`. Keep the frontmatter stable so the agent can update it in place. +These files are player-facing: record what the PC has observed or could observe. +A hidden truth the PC has not yet learned belongs in `../../gm/`. + ```markdown --- name: diff --git a/campaigns/_template/world/npcs/README.md b/campaigns/_template/world/npcs/README.md index 05a9092..dd4e860 100644 --- a/campaigns/_template/world/npcs/README.md +++ b/campaigns/_template/world/npcs/README.md @@ -2,6 +2,9 @@ One file per NPC, named `kebab-case.md`. +These files are player-facing: record what the PC has observed or been told. A +hidden motive or an unrevealed identity belongs in `../../gm/`. + ```markdown --- name: