DATA CONTRACT — structured game data (the prose→code bridge)
STATUS: NEW — pipeline upgrade. Fixes the biggest worker bottleneck: design is written as prose bibles
(ENEMIES.md, ITEMS.md, ZONES.md…), and the game integrator (starborne-autobuild) has to re-interpret thatprose into code every run — lossy and slow. This contract adds a machine-readable mirror the game/integrator
can consume directly: gamedata.json. Workers now dual-write: the prose bible (for humans/wiki) andthe structured entry (for the game).
1. THE RULE
When a design worker adds or changes an entity (enemy, item, resource, zone, recipe), it updates both:
- the prose bible (as today — ENEMIES.md / ITEMS.md / ZONES.md / RESOURCES.md …), and
- the matching structured record in
gamedata.json(sameid).
gamedata.json is the integration source of truth. starborne-autobuild reads it and ports records into
starborne.html mechanically (stable shapes → far faster, far more faithful than parsing prose). If the two ever
disagree, the prose is the creative intent; the JSON is what the game runs — reconcile toward the prose.
2. SCHEMA (gamedata.json)
{
"version": 1,
"enemies": [
{ "id": "gloomwolf", "name": "Gloomwolf", "kind": "wolf", "power": 24, "tier": 1,
"region": "Z1", "behavior": "pack-lunge", "drops": ["wolf-pelt","sinew"], "inGame": true }
],
"items": [
{ "id": "iron-longsword", "name": "Iron Longsword", "type": "blade", "tier": "forged-iron",
"slot": "weapon", "recipe": { "ingot": 3 }, "atk": 10, "inGame": true }
],
"resources": [
{ "id": "copper", "name": "Copper", "tier": 1, "host": "rock-edge", "pickTier": 1, "inGame": true }
],
"zones": [
{ "id": "Z1", "region": "Hearthvale", "biome": "thorn", "tier": "forged-iron",
"fixed": { "buildings": ["cabin","forge-house","shop","shrine","ministry","d1-mouth"],
"npcs": ["gideon","mara-thatch","old-bemis","sister-wren"], "templates": 5 },
"random": { "resources": ["iron","copper","gem"], "monsters": ["gloomwolf","husk-villager","tithe-clerk","crow"],
"trees": ["meadow","thorn"], "questBuildings": ["bemis-field","bounty-board"],
"animals": ["hare","songbird"], "tiles": ["grass","forest","dirt","water","road","farm"] },
"keyItem": "lantern", "inGame": false }
]
}
Field rules: id = kebab-case, stable, never reused. inGame = whether starborne.html already implements it
(autobuild flips this to true after porting). power/tier/atk come from BALANCE.md. Keep records minimal but
complete enough to generate code without reading the prose.
3. WHO WRITES WHAT (ownership — prevents collisions/truncation)
starborne-design→enemies,items,resourcesrecords (+ ENEMIES/ITEMS/RESOURCES/NPCS/BUILDINGS prose).starborne-zones→zonesrecords (+ ZONES.md prose).starborne-autobuild→ reads gamedata.json, portsinGame:falserecords into the game, flips theminGame:true,
logs to INTEGRATION-BACKLOG.md. Never authors new design.
- One writer per file/array. Append/replace by
id; never rewrite the whole file blind.
4. SAFETY (every worker, every run)
Before editing any design file: copy it to design/.backups/<name>.<UTCstamp>.md (keep ~15 newest). After editing,
re-read and check the file did not shrink >25% vs the newest backup (truncation tripwire) and still ends with its
final section; if it did, restore from the newest backup and stop. gamedata.json must remain valid JSON
(parse-check after writing; restore on failure).