Design in progress · V1 is still in development.
The World Master's Manual (WMM for short) is an environment for people to build their world, define concepts within said world, record relationships between concepts, infer conclusions from said concepts and relationships, and check their world's consistency.
Think of it like a steerable Dwarf Fortress, but with a worse UI. It's a tool with which you can design your world, and then work with an agent to push said world forward. I'd like to call it "Lean for Loremasters" but it's not a proof checker, nor does it need to be.
Why World Master Manual?
I run a Dungeons & Dragons campaign that's been going on for over a year and a half now. My general workflow is whenever I have an idea I write it down (this takes anywhere from 5 minutes to 3 hours) and then sit on it for at least a week. If I still like it, and there are no holes, and it seems fun then I keep it. But after doing this for so long, the sheer bloat of my Obsidian Repo has reached a point where I consistently run into
BIG PROBLEMS
- I reinvent something I already thought of because I forgot.
- I lose track of why I made a decision, or what it even was.
- I lose a piece of my "writing voice" because it's been too long.
- I wrote something that contradicts something else.
- I'm reusing/rehashing the same bits/ideas/events/tropes.
One day, when I was playing around with the idea of typing my world, I discovered the CIDOC Conceptual Reference Model! CIDOC CRM is a "theoretical and practical tool for information integration in the field of cultural heritage" or more casually it's an intelligent way of concretely defining abstract concepts like events and entities within a historical context.
From there, I realized if you have the ontologies, you can begin writing axioms. Then, we can build a "snapshot" of the world based on entities and events. Then, we can validate said snapshot by evaluating pregenerated constraints. This then lets us slap on Git concepts like branches and commits, and lets us introduce our own concepts like "retcons" and "proposals". Everything after that is just UI gravy so of course I'd like to interact with this through Obsidian and some sort of agent harness to handle porting and consulting.
- Authoring & Interoperability Editor, graphs, Obsidian, import/export
- Agent Orchestration Context, models, tools, user steering
- Canon & Versioning Proposals, commits, retcons, branches
- Rules & Validation Constraints, consistency, plausibility
- World State Entities, relationships, facts, events
- Ontology / World Type System Concepts, properties, relations, axioms
A Brief Technical Example
I think the easiest way to showcase this is through a worked example. First, I'd like to highlight Protégé, OWL and HermiT as close analogues to WMM. Protégé is an editor for ontologies: for us this is CIDOC CRM implemented in TypeScript. OWL is the language used to express those definitions and HermiT is a small kernel that judges the validity of any given OWL ontology, as well as infers the relationships between these classes.
- Protégé “What am I creating?”
- OWL “What am I implying?”
- HermiT “What follows from this?”
So, hypothetically, if I wanted to design a simple succession model to some regency I'd do:
An eligible heir is a person who:
is a legitimate child of the previous ruler,
is an adult,
and is alive.
Then record these as properties under Charlemagne and Carloman I. I do not need to say "Oh by the way, these two are eligible heirs to the throne", my reasoner will do that for me. And my reasoner could also infer a succession crisis is soon to follow from this if these two exist at the same time...
I am not writing an if statement for every individual in the world.
I define the concepts and relationships, and ask what comes next.
Soufflé is a super cool example of the evaluation engine I want to emulate. It's a statically typed Datalog system, so you declare some typed relations, supply facts, etc. and then write out the rules that derive other relations. Its type checker then checks how certain relational attributes are used in said rules. Let's continue with the previous example:
Facts:
Adult(Charlemagne)
Alive(Charlemagne)
LegitimateChild(Charlemagne, PepinTheShort)
Adult(CarlomanI)
Alive(CarlomanI)
LegitimateChild(CarlomanI, PepinTheShort)
Rule:
A living adult legitimate child of Pepin the Short
is eligible for the Crown of the Franks.
With both heirs satisfying the rule, this yields:
Eligible(Charlemagne, CrownOfTheFranks)
Eligible(CarlomanI, CrownOfTheFranks)
But the key here is that we want a good interpretive structure for this: a user needs to be able to inspect the properties here! You can imagine something like:
Eligible(Charlemagne, CrownOfTheFranks)
│
└── Succession rule R1
├── Adult(Charlemagne)
├── Alive(Charlemagne)
└── LegitimateChild(Charlemagne, PepinTheShort)
The Type System
To be clear I am not referring to the TypeScript Interface.
Core Types and Relationships
Fundamentally, there are only 2 things: things in the world and claims about things in the world. You learn the first in grade school (hint, hint, starts with an n and rhymes with "neopronoun") but the second is really just an assertion. However, assertions should have a source and links to related records.
Descriptors:
Charlemagne : Person
CrownOfTheFranks : Office
Relationship definition:
holdsOffice(Person, Office)
Assertion:
Charlemagne holdsOffice CrownOfTheFranks
polarity: positive
time: [100, 110)
account: canonical
jurisdiction: France
recognition: De Jure
A "king" is generally an office held for life, but it's not a permanent property attachment. It's a relationship to an occupation, under a specific context, particularly scoped. For example:
- A coup could occur.
- A movement could begin that installs a court that does not respect the legitimacy of the Frankish Crown.
- A chronicler could be wrong!
These tidbits add life to a world. Events are almost identical as any accession gets an identity,
assertions describe the participants, place, time, and any established downstream effects. The claim
"language" has two very basic forms: an Atom, for a particular property or relationship,
and Exists, for whether anyone in a specified population satisfies a criterion.
Both have positive and negative forms.
Rules and Validation
Rules and validating are simple, but I should clarify that malformed statements are not "inconvenient" statements. Consider:
Well-formed:
holdsOffice(Charlemagne, CrownOfTheFranks)
Wrong subject type:
holdsOffice(RoyalPalace, CrownOfTheFranks)
Illustrative diagnostic:
holdsOffice expects a Person as its subject.
RoyalPalace is a Place.
Resolving this requires us to look at the institution, succession, claims, etc. More generally, the engine needs to surface this class of error as almost a question rather than a violation. What kind of problem did it find? What did it rely on? What do I need to change in order to reconcile this?
The World Engine
I give the engine a snapshot of my world at a point in time, some definitions and a proposal. The proposal could be a question, a request or even just a comment. The engine needs to evaluate the parts of that proposal the model actually expresses. It is not "simulating" anything. I am giving it some premises and asking it to draw a conclusion.
Representing a World
I will be clear: I am hand waving a decent chunk of logic under the magical property
of Prose. Prose is whatever is too hard or too complicated or too abstract
to encode. Obviously, as the engine evolves it will get harder to add to prose but this
is the main driving force behind me adding an agent harness: an LLM would do a pretty
good job as a... World Engine Consultant?
World snapshot
Definitions and their versions
Entity, event, and period descriptors
Assertion catalog and active assertion IDs
Sources and support records
Authored prose
Definitions establish the vocabulary we use to describe the world, whereas descriptors identify particular things. Everything else is rehashed. A small point I should clarify: we are tracking revision time of the "Git history" I talked about in the intro as well as event time. I, for one, retcon a decent amount and tracking these "parallel timelines" is a particularly desirable feature for me. The other thing is the UI: if the engine establishes something from existing premises, I want an inspectable result where I can click around and investigate and even debug.
Execution and State Changes
Authoring is simple (and needs to remain simple).
Propose changes
→ assemble a candidate snapshot
→ validate and explain the candidate
→ let the author revise the selection
→ approve that exact candidate
→ commit against the expected base
I want to be able to draft these as well, and approve whatever seems interesting to me. Branches specifically play a large part here, so I can jump around and figure out what works well for the "canon".
A Worked Example
Let's close out the story of Charlemagne and Carloman. Obviously, we have 2 heirs. But how do we select a winner. Well, if I have a clear plot in mind I could obviously just submit a proposal that selects Charlemagne and be done with it. But what if this is purely for world building? After all... does there need to be a crisis at all?
THIS is where the agent belongs in this application. It could retrieve the succession rules, existing factions, prior disputes, and neighboring states, then propose a coup, a council settlement, or even a partition! Better yet, it could use Wikipedia, realize that perhaps I was heavily inspired by real life events and propose a realistic finale! Those are possible developments which go beyond simple deductions.
This should draft a new proposal, that I can review and verify myself. If I like it, I'll add it to the canon. If not, well poor Charlemagne. I do think the most interesting thing here is that you can see a clear open-world distinction: missing information does not automatically make a proposition false. This is the axiom that creates the concept of "open-world". Furthermore, I need a way to port my world into this system... and I am not doing that by hand.
What Comes Next
Just gotta chug along. I'll probably update this when V1 drops!