feat(skills): add project-local world-building skill
Author gritty, disposition-gated Margreave content (lore bible + hand-authored quest/item/location/origin JSON) that reconciles against existing canon before writing, holds the world's hard-by-default / warm-when-earned NPC tone, and keeps the content_build --check gate green. - SKILL.md: read-before-write workflow, read-only on existing canon (propose diffs, require approval), build+check+pytest as the done bar. - references/schema.md: full bible + JSON contract, secrecy scale, gate model. - references/tone.md: tone contract + NPC disposition-warmth model. - scripts/canon_index.py: dumps existing ids for reconciliation. - evals/: 3 test cases (all green in isolated-worktree runs). Un-ignore /.claude/skills/ so project skills are versioned like code; all other .claude/ dirs (root + nested api/client) stay ignored. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HuHRPE7VfppUJEaoGBEUqZ
This commit is contained in:
137
.claude/skills/world-building/SKILL.md
Normal file
137
.claude/skills/world-building/SKILL.md
Normal file
@@ -0,0 +1,137 @@
|
||||
---
|
||||
name: world-building
|
||||
description: >
|
||||
Author gritty, dark, disposition-gated world content for Code of Conquest (the
|
||||
Margreave). Use this WHENEVER the user wants to write, expand, or add lore,
|
||||
storylines, plot threads, secrets, factions, regions, towns, dungeons, NPCs and
|
||||
their knowledge/dialogue, quests, items, locations, or starting origins — even
|
||||
if they don't say "world-building" or name the content/ folder. Triggers on
|
||||
"write an NPC", "add a town/region/faction", "new quest", "a secret the party
|
||||
can uncover", "expand the Tallow Reach", "flesh out Duncarrow", "someone the
|
||||
player meets on the road", "cursed item", "give me a storyline", and the like.
|
||||
The skill reconciles new content against existing canon (never contradicting or
|
||||
silently changing it), writes it in the exact source format the content build
|
||||
tool consumes, keeps NPCs true to the world's hard, uncaring tone (warm only
|
||||
when disposition is earned), and verifies the build stays green. Do NOT use it
|
||||
for engine/UI code, prompts (/api/prompts), or combat rules.
|
||||
---
|
||||
|
||||
# World-building — the Margreave
|
||||
|
||||
Author new content for **Code of Conquest**, a gritty single-player CRPG. Read
|
||||
`CLAUDE.md` (repo root) once per session for the charter — this skill assumes it.
|
||||
|
||||
## The one rule that governs everything you write
|
||||
|
||||
> **Code owns state. AI owns text.** (charter §2)
|
||||
|
||||
You are authoring *static content*, not runtime state. Facts, personas, places,
|
||||
and knowledge chains are text the engine references by stable **id**. You never
|
||||
write initial disposition numbers into world content, never gameplay logic. A
|
||||
starting *value* (where the player begins, a seeded disposition) belongs to an
|
||||
**origin**, never to a town or NPC.
|
||||
|
||||
## The two things that make this hard
|
||||
|
||||
1. **New content must not contradict old content.** The build tool checks
|
||||
structure (ids resolve, secrecy routes correctly) but it CANNOT tell that you
|
||||
just described the north road as untraveled when canon says elves walk it. A
|
||||
contradiction ships silently and the DM narrates a broken world. So:
|
||||
**read the existing canon before you write a word**, and treat every existing
|
||||
file as read-only unless the user explicitly approves an edit (see below).
|
||||
|
||||
2. **The tone is specific and easy to get wrong.** Gritty, not grim. The world
|
||||
is hard and does not care about the player — but an NPC who has come to trust
|
||||
them becomes genuinely warm. Getting either pole wrong (grimdark misery, or
|
||||
friendly-NPC-from-hello) breaks the world. See `references/tone.md`.
|
||||
|
||||
## Workflow — follow in order
|
||||
|
||||
Make a todo per step.
|
||||
|
||||
### 1. Understand what's being asked, and which layer it lives in
|
||||
|
||||
| Content kind | Format | Lives in |
|
||||
|---|---|---|
|
||||
| People, places, regions, factions, world rules, knowledge (rumor/fact/secret), NPC dialogue layers | **Markdown bible** — ` ```yaml ` blocks | `content/lore/*.md` (source) |
|
||||
| Quests / story skeletons | Hand-authored JSON | `content/world/quests/` |
|
||||
| Items (incl. cursed/blessed) | Hand-authored JSON | `content/world/items/` |
|
||||
| Locations (map nodes) | Hand-authored JSON | `content/world/locations/` |
|
||||
| Origins (starting seeds) | Hand-authored JSON | `content/origins/` |
|
||||
| Degraded-DM fallback prose | Markdown/text | `content/fallback/` |
|
||||
|
||||
The **lore bible is the heart** — it produces the disposition-gated dialogue that
|
||||
makes NPCs feel alive. `content/world/` and `content/server/` under `canon/`,
|
||||
`topics/`, and `npcs/` are **BUILT from the bible — never hand-edit them.** The
|
||||
JSON under `quests/`, `items/`, `locations/`, and `origins/` is hand-authored and
|
||||
loosely schema'd (POC seeds); edit those directly.
|
||||
|
||||
If a storyline you're writing implies a quest, item, or location that doesn't
|
||||
exist yet, say so and author the stub, or flag it — don't leave a dangling id.
|
||||
|
||||
### 2. Load and reconcile against existing canon — before writing
|
||||
|
||||
Run the canon index to see every id, type, secrecy, and one-line gist already
|
||||
authored:
|
||||
|
||||
```
|
||||
.venv/bin/python .claude/skills/world-building/scripts/canon_index.py
|
||||
```
|
||||
|
||||
Read the entries your new content touches (people it references, the region it
|
||||
sits in, secrets it brushes against). New content must slot into this without
|
||||
contradiction. Reuse existing ids in `related:` rather than inventing parallel
|
||||
ones. If your idea only works by *changing* something already canon — a fact's
|
||||
body, a disposition, who knows what — **STOP.** Do not edit. Present the exact
|
||||
before/after change and the reason, and get explicit approval first. New files
|
||||
and new entries need no approval; edits to existing canon always do.
|
||||
|
||||
### 3. Draft in the correct format
|
||||
|
||||
- **Bible entries:** see `references/schema.md` for the full field-by-field
|
||||
contract, the id/namespace/type rules, the secrecy scale, and the knowledge-gate
|
||||
model. Match the voice and structure of `content/lore/duncarrow.md` — it is the
|
||||
reference specimen.
|
||||
- **Hand-authored JSON:** mirror the shape of the existing file in that folder
|
||||
(`references/schema.md` documents each). Keep ids stable and lowercase-snake.
|
||||
|
||||
Write NPCs to the tone and disposition-warmth model in `references/tone.md`. A
|
||||
hard NPC starts guarded (`cold`/`neutral`, sometimes reachable-`hostile`),
|
||||
withholds more than a stranger would expect, and both *reveals more* and *softens
|
||||
in manner* as the player climbs their ladder. That warmth is earned, never
|
||||
default — it's what the five-rung gate system exists to deliver.
|
||||
|
||||
### 4. Build and verify — not done until green
|
||||
|
||||
The build regenerates `content/world/` + `content/server/` from the bible and the
|
||||
`--check` gate is what CI enforces (`.github/workflows/content-build.yml`). Run,
|
||||
from repo root, with the repo venv active (`source .venv/bin/activate`) — the
|
||||
`content_build` package lives under `tools/`, so `PYTHONPATH=tools` is required:
|
||||
|
||||
```
|
||||
PYTHONPATH=tools python -m content_build # regenerate world/ + server/ from lore/
|
||||
PYTHONPATH=tools python -m content_build --check # must exit 0: fresh, valid, no orphans, no secrecy leaks
|
||||
PYTHONPATH=tools python -m pytest tools/content_build/tests -q # schema + secrecy + cli coverage
|
||||
```
|
||||
|
||||
(If `python` isn't found, the venv isn't active — use `.venv/bin/python`.)
|
||||
If any step fails, read the `BUILD FAILED` / `STALE:` message — it names the
|
||||
source file and line — fix the bible, rebuild, recheck. Never hand-edit the
|
||||
generated JSON to make `--check` pass; fix the source. (Hand-authored JSON under
|
||||
quests/items/locations/origins isn't built — the build tool ignores it. If you
|
||||
touched those, just confirm they're valid JSON.)
|
||||
|
||||
### 5. Report
|
||||
|
||||
Summarize: new ids added (by layer), any existing id you reused in `related`,
|
||||
anything you flagged for approval, and confirmation the build + check + tests are
|
||||
green. Update `content/lore/canon-roadmap.md`'s Authored/Pending lists if you
|
||||
added a new bible file or closed out a pending thread.
|
||||
|
||||
## Reference files
|
||||
|
||||
- `references/schema.md` — the complete bible + JSON schema, all validation rules,
|
||||
the secrecy scale, the knowledge-gate model, worked examples. Read before
|
||||
authoring bible entries.
|
||||
- `references/tone.md` — the Margreave's tone contract and the NPC
|
||||
disposition-warmth model. Read before writing any NPC or narrative body.
|
||||
Reference in New Issue
Block a user