Architecture overview
Canwu is a headless simulation engine: it has no renderer or UI of its own. Your application, whether a game, a research tool, a debug client, or an AI agent, links it as a Rust library. The application changes the world by submitting commands and reads it through snapshots, events, and actor-relative views. Only the engine’s runtime holds the live world, and it changes that state only while settling commands and scheduled work.
The layers at a glance
Section titled “The layers at a glance”Select a layer to see its crates, or switch to Follow a command to step through one command from submission to replay.
Public API boundary · code above this line uses only canwu-api
Engine internals · reached only through canwu-api
Your application
Owns rendering, input, the real-time clock, accounts, and historical content. It depends on canwu-api, registers the plugins it needs, submits commands, and reads the results.
Reference client in this repository
canwu-debugDesktop debug client (egui) built on the public API and the reference integrations
Domain plugins
Domain extensions add reusable rules as simulation plugins built on canwu-api. Register only the ones you need, or write your own. Reference content packs supply data, and reference integrations combine the pieces into small worlds you can run and copy.
Domain extensions (published on crates.io)
canwu-resourceResource accounts, reservations, transfers, and fulfillmentcanwu-productionProduction processes, facilities, work orders, and outputcanwu-movementMovement orders, route legs, and capacity poolscanwu-militaryForces, operations, combat, and occupationcanwu-societySocial diffusion between population groupscanwu-cultureCulture authoring, compilation, and lifecyclecanwu-lawLegal procedures, versioned law, and applicability (experimental)canwu-technologyTechnology from evidence to adoption and diffusioncanwu-fiscalFiscal institutions, procedures, and assessmentscanwu-informationDocuments, copies, access, and interpretationcanwu-correspondenceLetters, addresses, carriers, and interceptioncanwu-history-researchOptional research assessments for technology runs
Reference content packs
canwu-ming-fiscalVersioned, source-cited Ming fiscal datacanwu-economy-reference-contentEconomy model cards and cited datacanwu-military-reference-contentSynthetic (non-historical) military rulesets for the reference integration
Reference integrations (repository only, not published)
canwu-reference-worldSmall world with armies and territories, used by the starter examplecanwu-economy-referenceGrain loop with production, transport, and military supplycanwu-force-supply-referenceMilitary supply as a second resource consumercanwu-military-referenceThe military extension running in the reference worldcanwu-ming-fiscal-referenceHongwu, Wanli, and Hongguang fiscal scenarios
canwu-api
The engine crate your application depends on; extension crates build on it too. Its Canwu type creates and advances a run, accepts commands, returns detached snapshots and actor-relative views, and saves, forks, and replays runs. It re-exports the types you need from the crates below.
Main calls
Canwu::new_with_pluginsCreate a run from a scenario and a plugin listenqueue_commandQueue a command for a simulation timeadvance_canonicalAdvance time and settle everything that falls dueviewer_for_actorRead the world as one actor knows itevents · explainList what happened and ask whysnapshot_json · fork · replay_from_journalSave, branch, and replay a run
canwu-sim
Holds the authoritative state. It queues incoming commands, runs scheduled work, and settles due work in boundaries: one all-or-nothing pass at one simulation time, run in 14 fixed phases. If anything fails, the whole boundary rolls back. It also records the evidence and hashes used for saves and replay. Applications reach it only through canwu-api.
Crate
canwu-simRuntime, scheduling, settlement, plugins, persistence, hashing, and replay
Models and mechanisms
Data types that plugins and applications reach through canwu-api: what happened and why, what each actor knows, pending decisions, and route and transport records. The runtime itself uses the event, knowledge, and decision types.
Crates
canwu-eventEvents with their cause, audience, and evidence referencescanwu-knowledgeWhat each actor knows, with source, confidence, and agecanwu-decisionDecision tickets, controllers, and policiescanwu-routingRoute planning where travel times change over timecanwu-transportTransport runs, bookings, handoffs, and capacity pools
Foundation
Typed IDs, deterministic random numbers, schema metadata, and simulation time arithmetic. Every other crate builds on these two.
Crates
canwu-coreStable IDs, deterministic random numbers, and schema primitivescanwu-timeSimulation time and checked duration arithmetic
Step 1 of 7
Build a command
Your client creates a typed command. In the starter example, the reference world wraps a MovementCommand into a command envelope.
let envelope = order_movement(Issuer::Actor(commander), &command)?;Step 2 of 7
Queue it
enqueue_command puts the request in the ingress queue for its due time and returns a receipt. Resending the identical request returns the same receipt; reusing its ID with different content fails. The world has not changed yet.
canwu.enqueue_command(due_at, priority, CommandRequest::new(id, revision, envelope))?;Step 3 of 7
Advance time
advance_canonical moves simulation time forward. Each batch of work that falls due is settled in one boundary.
canwu.advance_canonical(SimDuration::hours(19))?;Step 4 of 7
Settle the boundary
The engine checks the issuer's authority, the revision the command was based on, and its expected time. A rejected command is recorded with its reason. Plugin systems then run in 14 fixed phases and propose changes, which commit together or roll back together.
The 14 phases →Step 5 of 7
Record what happened
Committed changes produce events that carry their cause and audience. Characters' knowledge and reports are updated, and the replay journal gains one more boundary.
Step 6 of 7
Read it back
A player or agent reads through viewer_for_actor and sees only what that actor knows. Trusted host tools can also list events() and ask explain() why something happened.
Reading state safely →let viewer = canwu.viewer_for_actor(actor)?;Step 7 of 7
Save and replay
snapshot_json saves the run, and replay_journal returns its recorded inputs. replay_from_journal rebuilds the run from those inputs; equal checkpoint hashes show the replay is exact.
Save, replay, and fork →let replayed = Canwu::replay_from_journal(&[&plugin], &canwu.replay_journal())?; assert_eq!(replayed.checkpoint_hash(), canwu.checkpoint_hash());
- Your application depends on
canwu-apiand registers the plugins it needs. - Domain plugins are optional crates built on
canwu-api. First-party extensions get the same access as a plugin you write yourself, so you can replace any of them. canwu-apiis the supported public API. It re-exports the types you need from the crates below it.canwu-simis the private runtime behindcanwu-api. It owns the live state, the ingress queue, scheduling, settlement, persistence, and replay.- Models and mechanisms (
canwu-event,canwu-knowledge,canwu-decision,canwu-routing,canwu-transport) define shared data types;canwu-apire-exports them. - Foundation (
canwu-core,canwu-time) provides IDs, deterministic random numbers, and simulation time.
All crates and their dependencies
Section titled “All crates and their dependencies”This graph shows the direct dependencies declared in each crate’s Cargo.toml:
A → B means A depends on B, and external and dev dependencies are left out.
It opens at 250%; zoom between 50% and 600% with the buttons or the mouse wheel
inside the graph, and drag to pan.
View dependency graph source
flowchart TB
subgraph Tools["Tools"]
Debug["canwu-debug"]
end
subgraph Extensions["Extensions"]
Correspondence["canwu-correspondence"]
Information["canwu-information"]
Society["canwu-society"]
Culture["canwu-culture"]
Law["canwu-law"]
Technology["canwu-technology"]
History["canwu-history-research"]
Fiscal["canwu-fiscal"]
Resource["canwu-resource"]
Production["canwu-production"]
Military["canwu-military"]
Movement["canwu-movement"]
end
subgraph Examples["Examples"]
MingFiscal["canwu-ming-fiscal"]
EconomyContent["canwu-economy-reference-content"]
MingReference["canwu-ming-fiscal-reference"]
ForceSupply["canwu-force-supply-reference"]
EconomyReference["canwu-economy-reference"]
ReferenceWorld["canwu-reference-world"]
MilitaryContent["canwu-military-reference-content"]
MilitaryReference["canwu-military-reference"]
end
subgraph PublicApi["Public API"]
Api["canwu-api"]
end
subgraph RuntimeMechanisms["Runtime and mechanisms"]
Sim["canwu-sim"]
Transport["canwu-transport"]
Routing["canwu-routing"]
end
subgraph Models["Models"]
Decision["canwu-decision"]
Event["canwu-event"]
Knowledge["canwu-knowledge"]
end
subgraph Foundation["Foundation"]
Core["canwu-core"]
Time["canwu-time"]
end
Debug --> Api
Debug --> MingReference
Correspondence --> Api
Correspondence --> Information
Information --> Api
Society --> Api
Culture --> Society
Culture --> Api
Law --> Api
Technology --> Api
History --> Api
History --> Technology
Fiscal --> Api
Resource --> Api
Production --> Api
Production --> Resource
Production --> Technology
Military --> Api
Movement --> Api
MingFiscal --> Api
MingFiscal --> Fiscal
EconomyContent --> Api
EconomyContent --> Production
EconomyContent --> Resource
EconomyContent --> Technology
MingReference --> Api
MingReference --> Fiscal
MingReference --> MingFiscal
MingReference --> ReferenceWorld
ForceSupply --> Api
ForceSupply --> EconomyContent
ForceSupply --> Resource
EconomyReference --> Api
EconomyReference --> EconomyContent
EconomyReference --> ForceSupply
EconomyReference --> Production
EconomyReference --> ReferenceWorld
EconomyReference --> Resource
EconomyReference --> Technology
ReferenceWorld --> Api
MilitaryContent --> Api
MilitaryContent --> Military
MilitaryReference --> Api
MilitaryReference --> Military
MilitaryReference --> MilitaryContent
MilitaryReference --> ReferenceWorld
Debug --> ReferenceWorld
Api --> Core
Api --> Decision
Api --> Event
Api --> Knowledge
Api --> Routing
Api --> Sim
Api --> Time
Api --> Transport
Sim --> Core
Sim --> Decision
Sim --> Event
Sim --> Knowledge
Sim --> Time
Transport --> Core
Transport --> Routing
Transport --> Time
Routing --> Core
Routing --> Time
Decision --> Core
Decision --> Time
Event --> Core
Event --> Time
Knowledge --> Core
Knowledge --> Time
Four rules the design follows
Section titled “Four rules the design follows”- State changes through commands. Clients submit commands; plugins submit proposals from their boundary systems. The runtime validates both and commits them at a boundary.
- Every run is reproducible. Time, scheduled work, system order, and random draws follow fixed rules, so a replay of the journal produces the same checkpoint hash.
- Knowledge belongs to characters. The runtime keeps the true state apart from what each character knows. Players and agents read through actor-relative views.
- History is recorded with its causes. Every event keeps its cause, audience, and correlation ID, so you can ask the engine why something happened.
Where the rules live
Section titled “Where the rules live”The engine keeps period-specific rules out of its core. They live above
canwu-api, in four forms:
| Kind | What it provides | Example |
|---|---|---|
| Domain extension | Reusable mechanics as simulation plugins | canwu-resource, canwu-movement |
| Reference content pack | Versioned data for an extension, with sources | canwu-ming-fiscal |
| Reference integration | A small runnable world that combines extensions and content | canwu-economy-reference |
| Starter kit | A runnable example you copy and modify | the starter example in canwu-reference-world |
View diagram source
flowchart TB
Engine["canwu-api + canwu-sim"] --> Domain["Domain extensions"]
Domain --> Pack["Reference content packs"]
Domain --> Integration["Reference integrations"]
Pack --> Integration
Integration --> Starter["Starter kits"]
Starter -. "copy and modify" .-> App["Your game or research tool"]
Domain -. "register directly" .-> App
Pack -. "reuse directly" .-> App
A few examples show how ownership is split:
- Movement.
canwu-transportholds plain records: orders, runs, itinerary changes, handoffs, bookings, and capacity pools.canwu-movementis the plugin that runs them: it admits movement orders, settles each leg when it falls due, allocates capacity pools, and publishes movement reports to the characters who should receive them. Incidents, hazards, and hostility stay in your own systems, together with the random draws that decide them. - Correspondence.
canwu-correspondenceowns letters from demand to delivery: address lookup, routes, carriers, disasters, and interception. It builds oncanwu-information, which owns documents, copies, and interpretation. - Economy.
canwu-resourceowns conserved quantities and their fulfillment.canwu-productionconsumes resources and technology evidence to run facilities and work orders.canwu-economy-referencecombines both with transport and military supply in a seasonal grain loop. Its scarcity and price-pressure numbers are read-only projections, and it reports a price only when a trade, quote, official rate, or contract supplies one.
For the owner of every cross-plugin contract (transition manifests, access grants, delegated carriers, and so on), see model ownership.
Crates
Section titled “Crates”Foundation, models, and runtime
Section titled “Foundation, models, and runtime”| Crate | Responsibility |
|---|---|
canwu-core |
Typed IDs, deterministic random numbers, and schema metadata |
canwu-time |
Simulation time and checked duration arithmetic |
canwu-event |
Event envelopes with cause, audience, and structured fields |
canwu-knowledge |
What each actor knows, with source, confidence, and age |
canwu-decision |
Decision tickets, controllers, deterministic evaluation, and the policy SDK |
canwu-routing |
Route planning where travel times change over time |
canwu-transport |
Records for transport runs, itinerary changes, handoffs, bookings, and capacity pools |
canwu-sim |
Private runtime: state, scheduling, plugins, settlement, persistence, hashing, and replay |
canwu-api |
Public API: commands, domain records, views, snapshots, evidence, and replay |
Domain extensions (published, optional)
Section titled “Domain extensions (published, optional)”| Crate | Responsibility |
|---|---|
canwu-resource |
Resource accounts with protected floors, demand, reservation, allocation, transfer, consumption, loss, access grants, and fulfillment |
canwu-production |
Processes, production sites, facilities, capacity, work orders, work in progress, projects, and output |
canwu-movement |
Movement orders, leg settlement, capacity-pool allocation, and movement reports, built on canwu-transport records |
canwu-military |
Forces, operations, combat, occupation, and pending effects that other domains settle and acknowledge; replace it if your game needs different combat rules |
canwu-society |
Social diffusion between population groups |
canwu-culture |
Culture authoring and compilation, plus a culture lifecycle that runs on canwu-society |
canwu-law |
Legal authoring, institutional procedures (including weighted, unit-block, and consultation stages), versioned law, and applicability; experimental |
canwu-technology |
Technology built from evidence: capability, implementation, adoption, and diffusion |
canwu-fiscal |
Fiscal procedures, regional adoption, assessment, execution receipts, and per-holder knowledge reports |
canwu-information |
Documents, copies, access, release, interpretation, and authenticity findings |
canwu-correspondence |
Addressed letters: demand, address lookup, routes, carriers, disasters, and interception |
canwu-history-research |
Optional research assessment plugins for technology runs |
Reference content packs (published)
Section titled “Reference content packs (published)”| Crate | Responsibility |
|---|---|
canwu-ming-fiscal |
Source-cited fiscal content from the early Ming to the Southern Ming, with coverage declarations |
canwu-economy-reference-content |
Economy model cards, citations, and coverage declarations, with explicit unknown and not-applicable states |
canwu-military-reference-content |
Versioned synthetic military rulesets for the military extension |
Reference integrations and tools (repository only)
Section titled “Reference integrations and tools (repository only)”| Crate | Responsibility | Also depends on |
|---|---|---|
canwu-reference-world |
A small example world (armies, people, territories, letters), its movement plugin, projection, routing adapter, and the starter example |
only canwu-api |
canwu-ming-fiscal-reference |
Runnable Hongwu, Wanli, and Hongguang fiscal scenarios | canwu-fiscal, canwu-ming-fiscal, canwu-reference-world |
canwu-force-supply-reference |
Military supply as a replaceable resource consumer, with a requisition saga | canwu-resource, canwu-economy-reference-content |
canwu-economy-reference |
A runnable grain loop combining resources, production, transport, force supply, scarcity, and price evidence | canwu-resource, canwu-production, canwu-technology, canwu-economy-reference-content, canwu-force-supply-reference, canwu-reference-world |
canwu-military-reference |
The military extension and its synthetic content running in the reference world | canwu-military, canwu-military-reference-content, canwu-reference-world |
canwu-debug |
Desktop debug client built on the public API and the reference integrations | canwu-reference-world, canwu-ming-fiscal-reference |
Domain systems
Section titled “Domain systems”Domain systems supply the concrete rules for knowledge, decisions, resources, war, taxes, and more, and each one has its own design page. The domain systems page lists all eight and the crates that provide them.
Further reading
Section titled “Further reading”- Settlement: the 14 phases of a boundary, allocation, commit, and rollback
- Events: causes, audiences, and explanations
- Randomness: how random draws stay replayable
- Guides: integrating, reading, saving, and extending
- Get started: runnable examples