The rules a character is made of, with no screen attached. Races, callings and skills become static tables in code; blurbs stay content (hand-written, like items/), so the content BOM stops blocking the engine. The sheet stores only what was rolled or chosen and derives the rest — one source of truth, and the M5 level curve becomes a function change rather than a migration. Creation is seeded. The creation Dictionary carries a seed, not a stat block: construct reconstructs the RNG and rolls the attributes itself, so the same seed yields an identical character and the UI cannot inject a number. §10's seeding argument, applied where the races spec says it first matters. 3d6 with a hard floor of 8. Straight 3d6 puts a ~9% chance on a primary the +3 pool cannot rescue — a Hedge-Mage with a -1 MAG modifier is not grit, it is the "fine" §7 forbids, paid for twenty hours. Lands the two migrations the races spec said to do at M4 and not silently: class_id -> calling_id (the contract should say what the world says) and a required race_id, so api/app/prompts.py can render "a beastfolk cutpurse" instead of "a sellsword". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QYa9u7Kdxv5gX4AnwWexy8
/docs — cross-cutting docs
Anything affecting both client and api, plus planning and roadmap. Side-specific docs live in /api/docs and /client/docs.
Put here:
roadmap.md— phases, POC scope, what's nextadr/— Architecture Decision Records- Shared contracts — canon log schema, tag syntax, retry policy (§11, §12)
- Anything spanning the HTTP boundary
The charter itself — CLAUDE.md — stays at the repo root. It is the source of truth; these docs elaborate, they do not override it.