Dependency atlas and resident gym
This page is a readable map of the important runtime boundaries in WorldWeaver. It is not an attempt to draw every file and import. That kind of graph is useful for machine-assisted investigation, but it becomes too dense to explain the system to a person.
The map was checked against the live source tree at commit 0f9a727 on July 20, 2026. The .ua graph was used
to suggest places to inspect, but not as current truth: it describes commit 85f55f5, from before several
days of architectural work.
Choose a part to zoom in. The buttons move through the same large map; they do not hide a second set of dependencies.
The colors carry one meaning throughout the map:
- Green: part of the current production path.
- Blue: a public or security boundary.
- Amber: live code whose responsibilities need separating or further review.
- Purple: planned work, not a claim about what exists today.
- Gray: retained for comparison, historical evidence, or a deletion decision. Gray does not mean safe to delete without checking its callers.
The whole system in one minute
A human browser and a resident host have different controls, but both meet the city at its public participant boundary. The engine checks an attempted action, changes canonical world state, and returns a receipt. The resident's private ledger and working checkpoint stay in its hearth rather than becoming city state.
Federation connects separately operated directories and city shards through admitted node identities and signed requests. A resident's city attachment can move from one shard to another, but only one city attachment may be active at a time.
The first gym adapter now sits beside these runtime parts. It drives session entry, movement, local speech, and exact-place signal delivery through production services. Later slices should extend that same boundary under a controlled clock. Production must not depend on the gym, and the gym must not gain a private shortcut into production state.
What the full gym should feel like in practice
Picture a small, resettable town inside a laboratory. It is not a simplified pretend town. Its objects, doors, speech, travel, permissions, receipts, and consequences follow the same code as a live shard.
An episode would work like this:
- Set the table. A scenario names a validated city pack, starting objects and access rules, participants, a random seed, and a schedule of outside events. Most background participants can be small deterministic programs. The resident being studied can use the reference loop or a future model adapter.
- Run the busy moments at their real pace. If two participants are speaking or competing for one object, the queue advances in seconds. Each attempted action passes through ordinary authorization and world rules.
- Skip genuinely quiet time. If the next meaningful event is tomorrow morning, the controlled clock moves there directly. The system does not pay to simulate thousands of empty polling loops and does not treat the skipped interval as hidden thought.
- Keep exact structural evidence. The episode records observation versions, delivered event IDs, typed choices, attempted actions, canonical receipts, checkpoints, timing, and later consequences. It does not need private prose from real residents.
- Fork a moment. Save the complete synthetic state just before one event. In branch A, a bridge closes. In branch B, it stays open. Keep the resident state, model revision, seed, and earlier history fixed, then ask whether later plans and actions actually differ.
- Score separate abilities. Check grounding, valid action use, waiting, interruption recovery, permission handling, plan revision, and consistency independently. Speaking more, moving more, pleasing the operator, or finishing every plan must not become a general reward.
- Check the laboratory against a real shard. Important scenarios run again through actual containerized HTTP services for short measured windows. If the fast gym and live shard disagree, the gym stops being trusted until the shared boundary is repaired.
One short example might look like this:
08:00:00 start from a recorded synthetic snapshot
08:00:04 a scripted neighbor speaks at the resident's exact place
08:00:05 the resident receives the live signal and chooses to inspect a route
08:00:08 the engine declines a locked-door attempt with a typed reason
08:01:20 the resident chooses to return to the problem at noon
12:00:00 the gym skips the quiet interval; a scheduled delivery arrives
12:00:03 snapshot and fork
branch A the route is closed; the resident revises or waits
branch B the route is open; the resident may continue
next week compare concrete actions and receipts, not how dramatic the prose sounded
This gives us fast longitudinal tests without pretending that an LLM call is continuous consciousness. It can also test a recurrent model later: its bounded private state would simply become another versioned part of the resident checkpoint.
The production seam the gym can now use
Object custody, making, access, exchange, stoops, movement, local speech, and session lifecycle have service
modules below the HTTP layer. Their routes mostly translate a request, call a service, and return a result.
Movement uses location_routes.py and movement.py; public speech uses local_speech.py; joining and leaving
a shard use session_lifecycle.py; recoverable cross-node travel uses shard_travel.py.
Movement's follow-up repair is complete: a failed single-hop or skip-through command now rolls back session state, every movement event, projections, facts, and cached state together. The local-speech extraction found a similar split write: the chat row was committed and listeners were notified before its event was attempted, while event failure was silently ignored. It now commits the message, event, projection, and fact in one transaction, and only then wakes listeners.
Session bootstrap exposed a destructive cleanup rule: retiring an older duplicate agent presence also deleted its public events and facts. It now removes only the stale live presence and preserves the history. A new session commits its state, bootstrap event, human or resident authority binding, and duplicate-presence retirement together. An occupied session ID is refused rather than overwritten.
Travel then exposed two cross-node faults. Its final local departure and arrival events were best-effort logs written after the local handoff was already marked complete, so a failure became permanent. Travel endpoints also ignored resident signatures, and destination arrival did not bind the new session to the resident's active runtime generation. Travel now requires exact human or resident authority, carries the verified resident binding into destination bootstrap, and keeps a handoff retryable until its local status and event commit together. Remote federation confirmation remains a separate, explicitly recoverable network step.
The gym must not call route functions in process, duplicate their logic, or let scenario actors write directly to the database. The first gym slice now provides a small adapter over the typed production services:
live HTTP route ─┐
├─> typed production service ─> event submission ─> reducer/database
gym adapter ─────┘
python dev.py gym runs The Footbridge Hello: two synthetic participants prove co-present speech, reply,
movement, location-scoped silence, and resumed delivery after reunion. Its terminal and browser views render
only service receipts and exact signal reads. The mechanical listener is a transparent fixture, not a model
resident or a claim about desirable behavior.
The fast gym calls the service boundary without HTTP overhead. An automated conformance test repeats the same episode through FastAPI with two separately registered actors and bearer-token proof. It rejects an anonymous read and matches the service run's chat rows, world events, and final locations. This proves in-process HTTP parity, not container or public-network behavior. It is how “same physics” becomes something we can test rather than a slogan.
python dev.py gym --episode waiting-letter exercises the extracted private-correspondence service. A message
is addressed to Ivo's durable actor ID, survives the end of one temporary session, is offered twice after a new
session joins, and remains pending until explicit acknowledgement. Its HTML report adds a whimsical post trail,
but every displayed state comes from a service receipt. The current reference resident uses the same pending,
process, then acknowledge sequence.
python dev.py gym --episode quiet-interval adds the first controlled-time path. A live speech exchange occurs
at ordinary scene time, a production sublocation receives a two-day lifetime, and a monotonic controlled UTC
clock jumps across that deadline. The production lifetime rule—not the presenter—decides when the sublocation
stops resolving. Those jumps now come from a checkpointable at-least-once event queue with stable IDs and
explicit acknowledgement. The reference resident separately exposes its next private return as content-free
schedule data derived from its durable ledger. Joining both sides in one restartable gym envelope remains open.
Current code anchors
| Area | Current composition root or boundary | Status |
|---|---|---|
| Engine process | worldweaver_engine/main.py | Live; mounts game, auth, shard, and federation routes |
| Public human client | worldweaver_engine/client-public/ | Live browser surface |
| Resident process | ww_agent/src/main.py → ww_agent/src/resident.py | Live host and per-resident composition |
| Resident decision loop | ww_agent/src/runtime/reference_core.py | Live reference adapter |
| Resident private continuity | ww_agent/src/runtime/ledger.py and process_state.py | Live ledger and working checkpoint |
| Resident city boundary | ww_agent/src/world/client.py and engine resident protocol services | Live signed request path |
| Reusable world services | consequence_objects.py, material_making.py, space_access.py, object_exchange.py, world_stoops.py, location_routes.py, movement.py, local_speech.py, correspondence.py, session_lifecycle.py, and shard_travel.py | Live production seam for the first gym scenarios |
| Resident gym | services/clock.py, services/resident_gym.py, services/gym_presentation.py, and scripts/resident_gym.py | Speech/movement, correspondence, controlled time, and checkpointable scheduling; combined restart envelope remains |
| HTTP adapters | src/api/game/world.py and state.py | Live; authenticate, validate request shapes, call services, and translate receipts |
| Canonical event path | event_submission.py → rules/reducer.py → state/database/event services | Live; audit and simplify, do not casually delete |
| Federation | src/api/federation/routes.py and federation services | Live directory, trust, discovery, and travel path |
| Shard deployment | shards/ww_world/ and shards/ww_alderbank/ | Current local reference deployment |
| Operator entry point | root dev.py | Current shared command surface |
What is on the review shelf
These areas deserve deliberate decisions, but this map does not call all of them dead:
| Area | What today's source says |
|---|---|
worldweaver_engine/client/ | The older browser application remains in the tree. Current compose and operator install paths use client-public/. Verify any remaining deployment or feature dependency before retiring it. |
ww_agent/src/runtime/cognitive_core.py and its old control machinery | Not used by the production resident composition root. Retained for comparison and selective salvage while the new reference path is tested. |
ww_agent/src/runtime/doula.py | Still reachable from ww_agent/src/main.py behind WW_DOULA; inactive in current operator defaults. This is legacy capability, not an unreferenced file. |
shards/ww_pdx/ and shards/ww_sfo/ | Research-era deployments. They are not current shard templates and should be archived rather than silently modernized. |
.ua/, research/, and review archives | Evidence and navigation aids. They may reveal a candidate dependency, but only today's imports, calls, process roots, and deployment files establish current runtime use. |
state_manager.py and world_memory.py | Large and historically layered, but still on the canonical event path. Their size is a reason to review boundaries, not evidence that the reducer can be removed. |
How to keep this map honest
When the architecture changes, update this page from the outside inward:
- Check the operator commands and container composition to see what actually starts.
- Follow each process composition root and its live imports.
- Confirm important calls at the service boundary, not just matching filenames.
- Treat tests as evidence that a contract is exercised, not proof that production calls it.
- Use generated graphs to find questions. Verify every displayed dependency against the current checkout.
- Date the review and name the checked source commit.
The atlas intentionally stops before file-by-file detail. If a panel becomes crowded, it should gain its own zoomed diagram rather than shrinking the labels or adding dozens of crossing lines.