On this page
Compose a subsystem and inspect its impact๏
Prerequisite: research records. A composition pins a set of recorded spell versions as one named unit. Its identity follows its membership. Recompose adds or removes selected members and produces a successor; it does not erase the previous roster.
Read the unit at the right grain๏
Roster, history, and member differences come from the research record. Footprint, drift, and impact join the member versions to custody information. Missing custody is reported explicitly; it must not silently count as an empty dependency graph.
The subsystem lesson creates three real module worlds before forming its group. Impact considers the union of member effects and distinguishes effects inside the composition from effects outside it. The membership comparison remains at subsystem grain; select changed members for deeper code comparisons afterward.
Compose source separately๏
research_synthesize selects top-level functions or classes from a donor module
into a base module and returns composed source with a preview. A method is not a
top-level function. The workshop lesson exercises both replacement and addition
using two generated modules so the comparison has two genuinely different inputs.
Staged ancestry belongs to the next fresh world entry. If the candidate is abandoned, clear that staging explicitly so an unrelated later bind cannot inherit it.
The workflow in code๏
These are the core steps from the saved example. Use its complete linked script for all class definitions and setup.
1def main() -> None:
2 crystallizer = md.Crystallizer()
3 crystallizer.activate(
4 md.CrystallizerConfigurationBuilder().with_defaults().activate(),
5 )
6 research = md.MutationResearch()
7 configuration = research.create_configuration()
8 configuration.with_defaults().activate()
9 research.activate(configuration)
10
11 spellbook_configuration = (
12 md.SpellbookConfiguration(FRAME).with_defaults().finalize()
13 )
14 book = md.Spellbook(aetheric_frame=FRAME,
15 configuration=spellbook_configuration)
16 book.configure_aether_frame(
17 system_state="dynamic",
18 disposal=None,
19 disposal_method_names=None,
20 rift_enabled=True,
21 ai_native=True,
22 )
23
24 # AN EMPTY FRAME IS A REAL FRAME. `configure_aether_frame` declares the
25 # frame's LAW; `conjure` REALIZES it by giving it a root conduit, and
26 # that realization is what publishes it to the Nexus. Publication is
27 # gated on `rift_enabled` ALONE - the spell loop it runs iterates
28 # whatever the book holds, including nothing. So the frame below is
29 # conjured EMPTY and is immediately linkable; spells are cargo, not a
30 # precondition, and everything bound after this arrives incrementally.
31 book.conjure(name="workshop-root")
32
33 nexus = md.Nexus()
34 system_configuration = nexus.create_configuration()
35 system_configuration.with_rift_creation_enabled(True)
36 system_configuration.with_allowed_target_frame_names([FRAME])
37 nexus.activate(system_configuration)
38 rift_configuration = nexus.create_rift_configuration()
39 rift_configuration.with_space_type("codegen")
40 rift = nexus.create_rift(configuration=rift_configuration,
41 rift_name="workshop")
42 rift.mark_active()
43 rift.create_frame_link(FRAME)
44 commands = rift.space.command_system
45
46 # THE ROOM WRITES BOTH MODULE WORLDS. Validation gates materialization;
47 # a rejected verdict registers and publishes NOTHING.
48 print("THE ROOM WRITES ITS OWN MATERIAL:")
49 for module_name, source in ((BASE_MODULE, BASE_SOURCE),
50 (DONOR_MODULE, DONOR_SOURCE)):
51 verdict = commands.validate_codegen(source, frame_name=FRAME)
52 kept = commands.materialize_codegen(
53 source, module_name=module_name, frame_name=FRAME,
54 )
55 assert kept["materialized"] is True, kept
56 print(" %-26s validate(%s) -> materialize(ok)"
57 % (module_name, type(verdict).__name__))
58
59 # The import hook is installed, so plain import resolves onto the
60 # world object. THIS is what gives two spells two module worlds.
61 base_module = importlib.import_module(BASE_MODULE)
62 donor_module = importlib.import_module(DONOR_MODULE)
63
64 # DISTINCT CLASS NAMES, and that is not cosmetic. These are two
65 # INDEPENDENT binds, so both spells are visible at once - and two
66 # visible spells sharing a name make `meld("SpellName")` ambiguous,
67 # which the structural validator refuses outright. A distinct
68 # binding_name alone does NOT settle it; the name itself has to
69 # resolve, or the pair needs a spellframe. (Two versions on ONE
70 # lineage are exempt - they are one spell, not two.)
71 base = book.bind(spell=base_module.ReportBase, existence="unique",
72 permissions="create", binding_name="workshop-base")
73 donor = book.bind(spell=donor_module.ReportDonor, existence="unique",
74 permissions="create", binding_name="workshop-donor")
75 print(" bound from the generated modules -> custody minted")
76 print(" base:", base[:12], " donor:", donor[:12])
77
78 # THE DEFAULT IS KIND-AWARE, not a single fallback. Asked for a diff
79 # with no strategy, the room checks whether BOTH sides are
80 # compositions. If they are not, it pins "structural" - its reasoning
81 # layer - and calls down. If they ARE, it passes NO strategy at all and
82 # lets the engine's own "members" default answer. One verb, two
83 # vocabularies, chosen by what you handed it.
84 print()
85 print("DIFF IS DERIVED, and its default is KIND-AWARE:")
86 print(" spell pair -> the room pins `structural`")
87 print(" composition pair -> the room stands back; engine says `members`")
88 try:
89 _show("diff(default)", commands.research_diff(base, donor))
90 _show("diff(source)",
91 commands.research_diff(base, donor, strategy="source"))
92 _show("diff(parts)",
93 commands.research_diff(base, donor, strategy="parts"))
94 except RuntimeError as custody:
95 print(" custody read REFUSED:", str(custody)[:100])
96 return
97 print(" these two are spells, so `structural` was chosen FOR them")
98
99 # AN EXPLICIT ASK IS NEVER REROUTED. The room pins a default only when
100 # you supplied none; the moment you name a strategy it goes down
101 # untouched, and an unknown name surfaces the engine's own KeyError
102 # rather than being quietly answered by a different question.
103 try:
104 commands.research_diff(base, donor, strategy="no-such-strategy")
105 raise AssertionError("expected the engine's KeyError")
106 except KeyError as unknown:
107 print(" unknown strategy -> KeyError:", str(unknown)[:70])
108 print(" a default is a KINDNESS FOR SILENCE, never an override")
109
110 # THE GRAIN, learned the way the engine teaches it. `summarise` is a
111 # METHOD on the donor's Report, not a top-level function.
112 print()
113 print("THE WORKSHOP - compose, do not merge:")
114 try:
115 commands.research_synthesize(base, donor,
116 take_functions=["summarise"])
117 raise AssertionError("a method is not a top-level function")
118 except ValueError as grain:
119 print(" take_functions=['summarise'] REFUSED:")
120 print(" ", str(grain)[:112])
121 print(" the refusal NAMES the donor's real top-level parts")
122
123 # TWO MODULE WORLDS MEAN BOTH ACTIONS ARE REACHABLE.
124 replaced = commands.research_synthesize(
125 base, donor, take_functions=["render_header"],
126 )
127 assert replaced["base_module"] != replaced["donor_module"], (
128 "the whole point of generating two modules"
129 )
130 assert [row["action"] for row in replaced["selections"]] == ["replaced"]
131 print(" take_functions=['render_header'] -> REPLACED (base had one)")
132
133 added = commands.research_synthesize(
134 base, donor, take_functions=["render_footer"],
135 )
136 assert [row["action"] for row in added["selections"]] == ["added"]
137 assert "render_footer" in str(added["composed_source"])
138 _show("synthesize", added)
139 print(" take_functions=['render_footer'] -> ADDED (base had none)")
140 print(" 'added' is only reachable across TWO module worlds, which is")
141 print(" why this lesson generates them instead of typing them here")
142 print(" composed source + preview returned. NOTHING executed, bound")
143 print(" or recorded - a candidate is not a version")
144
145 # THE ANCESTRY STAMP - ambient, one-shot, survives until used.
146 print()
147 print("THE ANCESTRY STAMP:")
148 commands.research_stage_ancestry([base, donor])
149 print(" staged [base, donor] for the NEXT fresh world entry")
150 commands.research_clear_staged_ancestry()
151 print(" cleared without consuming - abandoning a composition without")
152 print(" this is how a later, innocent bind acquires false parents")
153
154 staged = commands.research_synthesize(
155 base, donor, take_functions=["render_footer"], stage_ancestry=True,
156 )
157 assert staged["ancestry_staged"] is True
158 print(" stage_ancestry=True stages [base, donor] in the same call")
159 commands.research_clear_staged_ancestry()
160
161 print()
162 print("compose in the workshop; the record books the outcome")
163 print("a version-control system that merged your source would be")
164 print("guessing, and this one refuses to guess")
Runnable examples๏
Composing a version in the workshop โ Expert 30
Compositions a subsystem as one unit โ Expert 14
A subsystems blast radius โ Expert 32