On this page

The room and its fixtures๏ƒ

๐ŸŸ  Advanced ยท Lesson 10

THE ROOM. Every Rift owns exactly one, and the law around it is stricter than people expect:

A RIFT OWNS ONE PRIMARY ROOM, ITS KIND IS CHOSEN ONCE AT CREATION, AND IT IS NEVER SWITCHED.

There is no room registry. There is no "active space". There is no swap, promote, or re-type verb. RiftSpaceType is the single input that fixes a Rift's capability posture FOR LIFE, and Rift reads it at creation to construct the matching RiftSpace subclass.

That is a design choice worth pausing on. A room you can re-type is a room whose permissions are a moving target, and every consumer holding a reference has to re-ask what it is allowed to do. Fixing the kind at birth makes the answer cacheable and makes an audit of "what can this rift do" a question about creation, not about now.

THE FIXTURES - every room carries the same SET, whatever its kind: space_id / space_name / owner_rift_id / space_kind / metadata frame_viewer - the read surface (TYPE VARIES BY KIND) workstation - the binding canvas (lesson 12) command_system - the verb surface (TYPE VARIES BY KIND) event_system - rift-local publish/subscribe memory_system - rift-local command/execution records action + category hooks - pre/post interception, unregister by id

So every room has the same fixtures BY NAME, and two of them differ BY TYPE: command_system and frame_viewer - what you may DO and what you may SEE. The other three are literally the same classes.

Lesson 11 takes that pair apart. (An earlier draft of these lessons claimed only command_system varied; the owner's 3.14t run proved frame_viewer varies too, and the corrected version is the better story - authority and visibility narrow TOGETHER.)

Before you run๏ƒ

Use the Advanced guide for prerequisite concepts. Run from a checkout with Melder installed and Python 3.14 free-threading selected. The collection download includes the level's local helper modules.

Run the saved script๏ƒ

python UX_and_AIX_experiences/03_advanced/10_the_room_and_its_fixtures.py
py -3.14t UX_and_AIX_experiences/03_advanced/10_the_room_and_its_fixtures.py

Download this collection ยท Source on GitHub

Public surface๏ƒ

md.RiftSpace via rift.space, the room fixtures, the one-room law. Room kind is passed as the STRING "static"; md.RiftSpaceType appears only in the doc-drift check below, where the enum itself is the subject.

Code๏ƒ

  1"""
  2TIER: advanced (10)
  3GOAL: THE ROOM. Every Rift owns exactly one, and the law around it is
  4      stricter than people expect:
  5
  6        A RIFT OWNS ONE PRIMARY ROOM, ITS KIND IS CHOSEN ONCE AT CREATION,
  7        AND IT IS NEVER SWITCHED.
  8
  9      There is no room registry. There is no "active space". There is no
 10      swap, promote, or re-type verb. `RiftSpaceType` is the single input
 11      that fixes a Rift's capability posture FOR LIFE, and `Rift` reads it
 12      at creation to construct the matching `RiftSpace` subclass.
 13
 14      That is a design choice worth pausing on. A room you can re-type is
 15      a room whose permissions are a moving target, and every consumer
 16      holding a reference has to re-ask what it is allowed to do. Fixing
 17      the kind at birth makes the answer cacheable and makes an audit of
 18      "what can this rift do" a question about creation, not about now.
 19
 20      THE FIXTURES - every room carries the same SET, whatever its kind:
 21        space_id / space_name / owner_rift_id / space_kind / metadata
 22        frame_viewer     - the read surface (TYPE VARIES BY KIND)
 23        workstation      - the binding canvas (lesson 12)
 24        command_system   - the verb surface (TYPE VARIES BY KIND)
 25        event_system     - rift-local publish/subscribe
 26        memory_system    - rift-local command/execution records
 27        action + category hooks - pre/post interception, unregister by id
 28
 29      So every room has the same fixtures BY NAME, and two of them differ
 30      BY TYPE: command_system and frame_viewer - what you may DO and what
 31      you may SEE. The other three are literally the same classes.
 32
 33      Lesson 11 takes that pair apart. (An earlier draft of these lessons
 34      claimed only command_system varied; the owner's 3.14t run proved
 35      frame_viewer varies too, and the corrected version is the better
 36      story - authority and visibility narrow TOGETHER.)
 37SURFACE EXERCISED: md.RiftSpace via rift.space, the room fixtures, the
 38                   one-room law. Room kind is passed as the STRING
 39                   "static"; md.RiftSpaceType appears only in the doc-drift
 40                   check below, where the enum itself is the subject.
 41VERIFY: rides the owner's 3.14t run; asserts are the contract.
 42
 43DOC DRIFT FOUND AND FIXED (2026-08-02): RiftSpaceType's docstring used to
 44document a FOURTH member - "dynamic: Legacy alias for codegen, retained
 45temporarily so older AR configuration inputs can still normalize during
 46the room rename." THERE WAS NO SUCH MEMBER, and no `_missing_` handler,
 47so RiftSpaceType("dynamic") raised. The docstring has been corrected to
 48state plainly that the three members are the whole set. The check below
 49still runs because the enum's shape is worth proving, not because the
 50docs are suspect.
 51"""
 52import melder as md
 53
 54
 55def main() -> None:
 56    nexus = md.Nexus()
 57    system_config = nexus.create_configuration()
 58    system_config.with_rift_creation_enabled(True)
 59    nexus.activate(system_config)
 60
 61    rift_config = nexus.create_rift_configuration()
 62    rift_config.with_space_type("static")
 63    rift_config.with_space_name("health")
 64    rift = nexus.create_rift(configuration=rift_config, rift_name="ops")
 65    rift.mark_active()
 66    print("rift active:", rift.is_active)
 67
 68    # ONE ROOM, AND THE SAME ONE EVERY TIME. `space` is not a lookup or a
 69    # factory - it is THE room, identical by identity on every read.
 70    room = rift.space
 71    assert rift.space is room, "a rift has one room, not a room registry"
 72    print("room:", type(room).__name__, "| kind:", room.space_kind)
 73
 74    # The room knows who owns it. Ownership is one-directional and fixed.
 75    assert room.owner_rift_id == rift.id
 76    assert room.space_name == "health"
 77    print("space_id:", room.space_id, "| name:", room.space_name)
 78    print("owner rift:", room.owner_rift_id == rift.id)
 79
 80    # THE FIXTURES. Same set BY NAME on every room regardless of kind.
 81    # Two of them differ BY TYPE - command_system and frame_viewer, what
 82    # you may DO and what you may SEE (lesson 11 takes that pair apart).
 83    fixtures = {
 84        "frame_viewer": room.frame_viewer,
 85        "workstation": room.workstation,
 86        "command_system": room.command_system,
 87        "event_system": room.event_system,
 88        "memory_system": room.memory_system,
 89    }
 90    for name, fixture in fixtures.items():
 91        assert fixture is not None, f"{name} should be present on every room"
 92        print(f"  {name:16s} {type(fixture).__name__}")
 93
 94    # THE TYPE IS NOT RE-SETTABLE. There is no verb for it - not a refusal
 95    # you catch, an ABSENCE you cannot call. Proving a negative honestly
 96    # means naming what does not exist rather than try/except-ing.
 97    for absent in ("set_space_type", "switch_space", "promote_space",
 98                   "retype", "activate_space"):
 99        assert not hasattr(room, absent), f"{absent} should not exist"
100    print("no re-type verb exists - the kind is fixed at creation")
101
102    # The room kind matches what the configuration asked for, and that is
103    # the ONLY place it was ever decided.
104    assert room.space_kind == "static"
105    print("configured \"static\" -> room kind:", room.space_kind)
106
107    # THREE MEMBERS, AND ONLY THREE. An input naming anything else fails at
108    # normalization rather than falling back - the correct behaviour for a
109    # value that fixes the room's posture for life. (A stale docstring once
110    # promised a fourth, "dynamic"; that has been corrected.)
111    members = [kind.value for kind in md.RiftSpaceType]
112    print("members:", members)
113    assert members == ["static", "capability", "codegen"]
114    try:
115        md.RiftSpaceType("dynamic")
116        raise AssertionError("expected ValueError - there is no such member")
117    except ValueError:
118        print("an unknown room kind is refused, not defaulted")
119
120    print()
121    print("one rift, one room, one kind, decided once and never again")
122    print("same fixtures by name; command_system and frame_viewer differ by type")
123
124
125if __name__ == "__main__":
126    main()

Check the outcome๏ƒ

The script contains its own assertions or demonstrated refusal paths. Run it to evaluate those checks against your installed version. The code above is taken directly from the saved file; no run output is invented here.

More advanced examples ยท Level guide

API contracts๏ƒ