Display strings derived from Callings/Races/Skills at call time. Retune a hit die and the card follows, because the card never knew the number. Prose stays in content; numbers stay in code; nothing is written twice. Deviation from the plan, approved by the human: the plan's test asserted the rendered line contains Callings.armor(id) — the RAW table value — while the plan's own ARMOR_WORD maps "none" to "no armour". "none" is not a substring of "no armour", so the Hedge-Mage failed. The card's copy is what the plan's docstring example shows, so the copy stands and the test was fixed: armor_word(id) is now public and the test asserts against the derived word. The guard is unchanged — hardcode an armour string and retune the table, and it still goes red. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
/client — Godot 4.7 game client
GDScript. Holds ALL game state and ALL game rules (charter §2, §4). The AI never mutates state; the client validates and applies everything.
Open: Godot 4.7, import this folder as the project (project.godot).
Responsibilities
- All state: stats, HP/MP, inventory, quest flags, Luck, disposition/approval (§8, §9)
- All rules: deterministic combat, Luck branch-selection, move validation (§6, §7, §10)
- The canon log — compact structured fact list, code-maintained, injected into every call (§11)
- Talks to
/apiover HTTP. No API key, ever. Knows one base URL + role endpoints (§4) - Degrades to authored fallback text (from
/content/fallback) when the API is down (§13)
Key rule — never do this (charter §2)
If an AI response directly sets a variable that persists, stop. Parse → validate → apply or discard.
See docs/ for scene structure, input model, and combat wiring.