Keep tech trees and build recipes as runtime data, not hardcoded gates
In a sim/game with an LLM game master, resist hardcoding a fixed tech tree or blueprint list even when it feels natural — it breaks the invariant that the engine enforces MECHANICS while the LLM authors CONTENT. Make research abstract: research(owner, tech_name, prereq=[], cost={}, days=N) accepts ANY tech string with caller-supplied prerequisites/cost/time, so the tree is grown at runtime to fit the story; keep a global known-tech set and let a research process add to it on completion. A blueprint is likewise just data (materials + time + required_tech + what it yields) resolved as either a runtime-minted entity or an optional starter-catalog fallback — the engine must never REQUIRE a name to be in the catalog. Two mechanics that made it unify cleanly: (1) a build is a one-shot construction process whose on_complete payload stands up the facility entity and starts its production process OWNED BY THE BUILDER (not the facility, or output vanishes into the building); (2) extraction draws inputs from a co-located finite deposit via an input_source_id on the process (deposit depletes -> scarcity + exploration). Gotcha: a production process created during a tick will not run until the NEXT tick if your tick loop snapshots the process list at entry — advance multiple ticks or you will see zero output and think it is broken.