Layout rules
The content tree — the contract for the
data/ tree.
data/
├── README.md this contract
├── tables/ one registry per file
│ ├── skills.srd.ron Table<SkillDef> (18)
│ ├── weapons.srd52.ron Table<Weapon> (38)
│ ├── weapon_masteries.srd52.ron Table<WeaponMasteryAssignment> (36)
│ ├── armor.srd52.ron Table<Armor> (12 + shield)
│ ├── cr_xp.srd52.ron Table<CrXp> (34)
│ ├── encounter_xp_budgets.srd52.ron Table<EncounterXpBudget> (20)
│ ├── advancement.srd.ron Table<AdvancementRow> (20)
│ ├── multiclass_spell_slots.srd.ron Table<SpellSlotRow> (20, SRD Multiclass Spellcaster table)
│ ├── damage_kinds.srd.ron Table<VocabRow> (13 — open vocabulary)
│ ├── schools.srd.ron Table<VocabRow> (8 — open vocabulary)
│ ├── creature_types.srd.ron Table<VocabRow> (14 — open vocabulary)
│ ├── languages.srd.ron Table<VocabRow> (16 — open vocabulary)
│ ├── quality_profiles.ron Table<QualityProfile> (5 classes × 7 tiers, ours)
│ ├── alignment.ron AlignmentRules (moral motive weights, ours)
│ ├── material_classes.ron Table<MaterialClass> (5, ours — [](../docs/adr/0070-vocabularies-are-registries.md))
│ └── terrain_tags.ron Table<TerrainTag> (7, ours — [](../docs/adr/0070-vocabularies-are-registries.md))
├── professions/ ours — one profession per file (17; the
│ └── {fisher,brewer,baker,farmer,miller,tanner,smith,mason,merchant,innkeeper,
│ harbor_clerk,fixer,noble,guildmaster,captain,priest,sage}.ron — canonical
│ set mirrors crates/engine/src/professions.rs
├── buildings/ ours — one building TYPE per file (21)
│ └── {smithy,tannery,carpentry,masonry,weaver,ovens,mill,mash_house,tavern,
│ fields,dock,mine,lumber_camp,pasture,manor,guildhall,watch_house,house,
│ town_wall,shrine,tower}.ron
├── races/ one race per file, subraces inside as variants
│ └── {dwarf,elf,halfling,human,dragonborn,gnome,half_elf,half_orc,tiefling}.srd.ron
├── classes/ one class per file, the SRD subclass inside
│ └── {fighter,rogue,cleric,barbarian,monk,paladin,ranger,bard,druid,sorcerer,warlock,wizard}.srd52.ron (12)
├── feats/ OPEN collection: one feat per file
│ ├── grappler.srd.ron SRD 5.1's ONE feat (prereq-only; riders ledgered)
│ └── {alert,savage_attacker,boon_of_truesight}.srd52.ron the SRD 5.2.1 feats
│ with engine substrate ; the rest is a mod surface
├── spells/ OPEN collection: one spell per file
│ └── {fire_bolt,magic_missile,fireball,cure_wounds,…}.srd*.ron (83: 79 SRD 5.1,
│ 4 SRD 5.2.1),
│ every one scoped to the class list the book
│ gives it — ; ALL of them, since the
│ one non-SRD file left for the private
│ book-mod tree at . No shipped spell
│ pulls: Effect::Pull's lock builds its own)
├── magic_items/ OPEN collection: one magic item per file
│ └── {plus_one_longsword,plus_one_chain_shirt,ring_of_protection,
│ cloak_of_protection,wand_of_magic_missiles}.srd.ron (5: the SRD starter set)
│ ring_of_resistance_{acid,…,thunder}.srd.ron (10: the SRD 5.1 Ring of Resistance gem table, one row per line)
├── conditions/ OPEN collection: one condition per file
│ └── {blinded,charmed,deafened,frightened,grappled,…}.srd52.ron (14)
│ unconditional ConditionComponent reads plus
│ contextual ConditionFact entries
│ {ability_guided_weapon,innately_sorcerous,raging,reckless,
│ walking_speed_flight}.ron (5 Original class-helper conditions)
├── traps/ OPEN collection: one trap per file
│ └── {poison_needle,poison_darts,fire_breathing_statue}.srd.ron (3: the SRD
│ "Traps" device samples; the container trap is
│ the poison needle — the rest a mod surface)
├── diseases/ OPEN collection: one disease per file
│ └── {sewer_plague,sight_rot,cackle_fever}.srd.ron (3: the SRD "Diseases"
│ sample diseases — a contraction save, an
│ incubation, an effect (exhaustion/condition/
│ check penalty), and a long-rest recovery save
│ track; the rest a mod surface)
├── creatures/ OPEN collection: one entity per file,
│ ├── humanoids/ in stable taxonomic folders
│ │ └── {commoner,guard,bandit}.srd.ron
│ ├── beasts/wolf ; undead/{skeleton,zombie} ; dragons/black_dragon_wyrmling
│ ├── fiends/dretch ; elementals/magma_mephit ; giants/ogre ; oozes/gray_ooze
│ ├── constructs/animated_armor ; monstrosities/worg ; fey/satyr
│ └── celestials/pegasus ; aberrations/gibbering_mouther ; plants/awakened_shrub
│ (the bestiary — one per type)
├── goods/ ours (unsuffixed) — one material/tool per file
│ └── iron_ore, iron_ingot, coal, timber, hide, leather, cotton, cloth,
│ sinew, bedroll, bed, smiths_tools, leatherworkers_tools,
│ carpenters_tools, weavers_tools (.ron, source: Original)
├── expected/
│ └── npc_blocks.srd.ron verification corpus (see Derivations)
├── art/ runtime pictures a row names by path (see below)
│ └── furniture/ one per furnishing good's `art:` field
└── names/ ours (unsuffixed) — per-race name tables
-
Art is named by path, and a mod layers it. A furnishing good’s
art:names a picture insideart/, e.g."furniture/trestle-table.webp". It is drawn from above facing north (back edge at the top,width_cellsacross,length_cellsdown, 128 px per cell) and the board rotates it for the other facings. A mod’s ownart/is searched before this one, so a mod replaces a picture by shipping the same path or adds one under a new path. A path that resolves nowhere fails the load. Every picture carries a provenance header that says whether it is an AI placeholder or who made it and under what licence; stamp one withcargo xtask art stamp( ). -
Registries vs. entities. Compact row collections (the SRD’s tables) live as ONE registry file per set under
tables/. Collections that will someday hold tens of thousands of entries (creatures, and later items, spells,…) grow one-file-per-entity inside stable taxonomic folders —creatures/humanoids/plus the thirteen monster folders (beasts/,undead/,dragons/,fiends/,elementals/,giants/,oozes/,constructs/,monstrosities/,fey/,celestials/,aberrations/,plants/) the bestiary filled, one exemplar per non-humanoid type.magic_items/is the README’s own “later items” made real — an entity collection, not atables/registry, because the SRD’s Magic Items chapter grows to thousands and a mod adds one as a file. Both kinds are OPEN: mods add weapons, armor, races, and creatures (the moddable-data amendment — data loads at boot). A creature’s optionaldoorsfield is a closed set ofEncounter,Battle,Form, andSummon; when absent it defaults to all four. Author at least one distinct door to narrow which builders and catalogues may enumerate the body. A swarm (any creature withswarm_member_size) never opensForm, whatever its list says: a form takes one body, and a swarm is many. -
Suffix + source provenance. A provenance suffix marks files whose content derives from an SRD, and names WHICH one:
.srd.ronfor SRD 5.1,.srd52.ronfor SRD 5.2.1. Every file’s top-level value also carries a requiredsourcefield (Srd51,Srd52, orOriginalin the base), and the two must agree —data_lock’sthe_suffix_and_the_source_field_agreefails the build otherwise, so the path can be trusted without opening the file. Book mods use their matchingPhb2024,Dmg2024,Mm2024,Tce, orXgesource; the loader refuses a missing source, a book source in base data, or a book/namespace mismatch. That is what makes*.srd*.ronauditable against the repository’sATTRIBUTION.md, which states the two grants separately. Files without a suffix (names/,goods/) are ours. -
id equals filename. For one-entity-per-file collections, the file stem IS the entity’s
id:half_elf.srd.ron↔id: "half_elf",guard.srd.ron↔id: "guard". The future parse-everything lock test asserts this. Ids are snake_case throughout — chosen over kebab because the pre-existingnames/files (half_orc.ron) already use it, and the race key contract (below) shares filename ids with them. -
No organization by tunables. Directories follow stable taxonomy ONLY — never CR, level, cost, or any other property that balancing may move. By-CR (or any) access is a load-time index. This is derive-don’t-store applied to layout.