On this page
Opening a rift๏
๐ Advanced ยท Lesson 09
OPENING A RIFT - and meeting melder's most repeated law for the third time in three lessons.
THE PATH (each step needs the one above it) nexus = md.Nexus() nexus.activate(nexus.create_configuration()) # lesson 08 rift_config = nexus.create_rift_configuration() rift_config.with_space_type("static") rift = nexus.create_rift(configuration=rift_config, rift_name="ops")
THE RIFT CONFIGURATION IS CONSUMED. create_rift() takes ownership. Hand the same configuration to a second create_rift() and it refuses with "RiftConfiguration has already been consumed." One configuration, one rift - the same one-shot law AetherConfigurationBuilder.build() follows (lesson 07). If you want two rifts, you ask the factory twice.
THE LAW YOU HAVE NOW SEEN THREE TIMES Melder never conflates "this exists" with "this is live". Every subsystem splits it into two bits, and only the names change:
lesson 07 config frozen / activated lesson 08 nexus is_configured / is_activated lesson 09 rift is_registered / is_active
Once you have seen it three times it stops being trivia and starts being the thing you predict. When you meet a melder object you have never used, look for its two bits first - presence and liveness are always separate questions, and the answer to one never implies the other.
WHAT THIS LESSON DELIBERATELY DOES NOT DO: AR targeting. That needs rift_enabled=True on the target frame's posture - the frame's opt-in to being observable, and it defaults False. Setting it is a FRAME concern, not a rift one, which is why it is not shown here: you posture the frame first, then attach. Rifts, rooms and workstations are what this lesson covers.
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/09_opening_a_rift.py
py -3.14t UX_and_AIX_experiences/03_advanced/09_opening_a_rift.py
Public surface๏
md.Nexus.create_rift_configuration, create_rift, md.RiftConfiguration, md.Rift, md.RiftSpaceType
Code๏
1"""
2TIER: advanced (09)
3GOAL: OPENING A RIFT - and meeting melder's most repeated law for the
4 third time in three lessons.
5
6 THE PATH (each step needs the one above it)
7 nexus = md.Nexus()
8 nexus.activate(nexus.create_configuration()) # lesson 08
9 rift_config = nexus.create_rift_configuration()
10 rift_config.with_space_type("static")
11 rift = nexus.create_rift(configuration=rift_config, rift_name="ops")
12
13 THE RIFT CONFIGURATION IS CONSUMED.
14 create_rift() takes ownership. Hand the same configuration to a
15 second create_rift() and it refuses with "RiftConfiguration has
16 already been consumed." One configuration, one rift - the same
17 one-shot law AetherConfigurationBuilder.build() follows (lesson 07).
18 If you want two rifts, you ask the factory twice.
19
20 THE LAW YOU HAVE NOW SEEN THREE TIMES
21 Melder never conflates "this exists" with "this is live". Every
22 subsystem splits it into two bits, and only the names change:
23
24 lesson 07 config frozen / activated
25 lesson 08 nexus is_configured / is_activated
26 lesson 09 rift is_registered / is_active
27
28 Once you have seen it three times it stops being trivia and starts
29 being the thing you predict. When you meet a melder object you have
30 never used, look for its two bits first - presence and liveness are
31 always separate questions, and the answer to one never implies the
32 other.
33
34 WHAT THIS LESSON DELIBERATELY DOES NOT DO: AR targeting. That needs
35 `rift_enabled=True` on the target frame's posture - the frame's
36 opt-in to being observable, and it defaults False. Setting it is a
37 FRAME concern, not a rift one, which is why it is not shown here:
38 you posture the frame first, then attach. Rifts, rooms and
39 workstations are what this lesson covers.
40SURFACE EXERCISED: md.Nexus.create_rift_configuration, create_rift,
41 md.RiftConfiguration, md.Rift, md.RiftSpaceType
42VERIFY: rides the owner's 3.14t run; asserts are the contract.
43"""
44import melder as md
45
46
47def main() -> None:
48 nexus = md.Nexus()
49
50 # A rift needs a live nexus underneath it - lesson 08's ladder.
51 system_config = nexus.create_configuration()
52 system_config.with_rift_creation_enabled(True)
53 nexus.activate(system_config)
54 assert nexus.is_activated is True
55 print("nexus enabled; rift creation permitted")
56
57 # The per-rift configuration is its own object with its own factory.
58 # Note the shape is identical to every other config in melder: with_*
59 # verbs that mutate and return self, ending in a terminator.
60 rift_config = nexus.create_rift_configuration()
61 assert isinstance(rift_config, md.RiftConfiguration)
62 rift_config.with_space_type("static")
63 rift_config.with_space_name("health")
64 print("rift configuration staged: static room named 'health'")
65
66 # create_rift finalizes the configuration on the way through - the same
67 # courtesy Nexus.activate() extended in lesson 08, and still the opposite
68 # of what Aether does.
69 rift = nexus.create_rift(configuration=rift_config, rift_name="ops")
70 assert isinstance(rift, md.Rift)
71 print("rift opened:", rift.rift_name, "| id:", rift.id)
72
73 # ONE CONFIGURATION, ONE RIFT. The object was consumed by the call.
74 try:
75 nexus.create_rift(configuration=rift_config, rift_name="ops-again")
76 raise AssertionError("expected ValueError: configuration consumed")
77 except ValueError as error:
78 print("second use refused:", error)
79
80 # THE TWO BITS, third appearance. Creation registered it; being
81 # registered is not the same as being live.
82 assert rift.is_registered is True
83 print("after create - registered:", rift.is_registered,
84 "active:", rift.is_active)
85
86 rift.mark_active()
87 assert rift.is_active is True
88 print("after mark_active - registered:", rift.is_registered,
89 "active:", rift.is_active)
90
91 rift.mark_inactive()
92 assert rift.is_active is False
93 assert rift.is_registered is True, "liveness went; registration stayed"
94 print("after mark_inactive - registered:", rift.is_registered,
95 "active:", rift.is_active)
96
97 # The rift owns a concrete room and a gate. The room's kind came from
98 # the configuration; the gate is the entry control (lesson 10 uses it).
99 assert rift.space is not None
100 assert rift.rift_gate is not None
101 print("room:", type(rift.space).__name__,
102 "| gate:", type(rift.rift_gate).__name__)
103
104 # Nexus is the registry - the rift can be found by id and by name.
105 assert nexus.has_rift(rift.id) is True
106 assert rift.id in nexus.list_rift_ids()
107 print("registered with nexus; rift ids:", len(nexus.list_rift_ids()))
108
109 print()
110 print("one configuration, one rift - create_rift consumes it")
111 print("presence and liveness are ALWAYS two bits, whatever they are named")
112
113
114if __name__ == "__main__":
115 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.