The canon-log schema and NewGame code already migrated to race_id/
calling_id + allowed_callings, but two copies of the roster outside
that schema were missed, and no parity test guards them:
- docs/canon-log.md (the cross-boundary contract doc) still documented
the OLD player shape and allowed_classes. Anyone building a player
block from the doc would get a 422.
- .claude/skills/world-building's schema reference still emitted
allowed_classes with two dead calling ids (assassin, priest). Author
a new origin with that skill and it fails origin.schema.json
(additionalProperties: false, allowed_callings required) AND, if that
ever loosened, silently allows zero callings at runtime.
Also:
- add schema tests rejecting a dead class_id field and an unknown
calling_id (priest)
- guard NewGame._validate's container types (spend/skills) so a
malformed JSON round-trip (null spend, string skills) produces a
front-loaded error list instead of a GDScript runtime crash
- extend the no-mechanics-in-content test to db.races, not just
db.callings
- rewrite the roadmap's M4 bullet: the two contract migrations landed;
only the creation screen and title->creation->shell flow remain
client: 250/250. api: 74 passed, 2 skipped. content_build --check: clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYa9u7Kdxv5gX4AnwWexy8