On this page
The describe ladder๏
๐ Advanced ยท Lesson 14
THE DESCRIBE LADDER - why the read surface is not one fat describe() per thing, and why that shape is aimed at agents.
Look at what ViewSpell offers for a single spell:
describe_spell_brief(...) the smallest useful answer describe_spell(...) the normal record describe_spell_detail(...) the long form describe_spell_payload(...) the raw payload
...and then NINE per-facet verbs that hand you exactly one slice:
describe_spell_identity describe_spell_source describe_spell_origin describe_spell_binding describe_spell_index describe_spell_resolution describe_spell_metadata describe_spell_research describe_spell_class_profile
ViewConduit is built the same way - brief / describe / topology / inventory / relationships / crosswalk, plus root and policy filters.
THIS IS A CONTEXT BUDGET CONTROL.
A human reading one spell does not care whether the payload is 400 bytes or 40,000. An agent with a finite context window cares enormously. The ladder lets a caller enumerate 400 spells at BRIEF, decide which three matter, and pay full price for only those three.
A single fat describe() forces the opposite trade: either it is thin and you cannot answer detailed questions, or it is fat and surveying anything is unaffordable. The ladder refuses that choice.
THE CHEAP RUNG IS ALWAYS list_* list_spells / list_conduits / list_root_conduits Names and ids first. Descriptions only for what survives the filter.
A NOTE ON THIS LESSON'S WORLD ViewSpell and ViewConduit are FRAME-SCOPED (lesson 13), and a freshly opened rift is contracted to no frames - so this lesson maps the ladder off the EXPORTED TYPES rather than off instances. That is not a workaround: THE LADDER IS A PROPERTY OF THE CLASS. You do not need a populated world to see the shape of the surface you will be paying for, which is exactly the point of surveying before you commit.
The HOST-SCOPED view (get_view_multiframe) needs no frame, so the cheapest rung of all really is callable before you have assigned anything - and this lesson proves that too.
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/14_the_describe_ladder.py
py -3.14t UX_and_AIX_experiences/03_advanced/14_the_describe_ladder.py
Public surface๏
md.ViewSpell, md.ViewConduit - the describe ladder, list_* enumeration, empty-world coherence
Code๏
1"""
2TIER: advanced (14)
3GOAL: THE DESCRIBE LADDER - why the read surface is not one fat
4 describe() per thing, and why that shape is aimed at agents.
5
6 Look at what ViewSpell offers for a single spell:
7
8 describe_spell_brief(...) the smallest useful answer
9 describe_spell(...) the normal record
10 describe_spell_detail(...) the long form
11 describe_spell_payload(...) the raw payload
12
13 ...and then NINE per-facet verbs that hand you exactly one slice:
14
15 describe_spell_identity describe_spell_source
16 describe_spell_origin describe_spell_binding
17 describe_spell_index describe_spell_resolution
18 describe_spell_metadata describe_spell_research
19 describe_spell_class_profile
20
21 ViewConduit is built the same way - brief / describe / topology /
22 inventory / relationships / crosswalk, plus root and policy filters.
23
24 THIS IS A CONTEXT BUDGET CONTROL.
25
26 A human reading one spell does not care whether the payload is
27 400 bytes or 40,000. An agent with a finite context window cares
28 enormously. The ladder lets a caller enumerate 400 spells at BRIEF,
29 decide which three matter, and pay full price for only those three.
30
31 A single fat describe() forces the opposite trade: either it is
32 thin and you cannot answer detailed questions, or it is fat and
33 surveying anything is unaffordable. The ladder refuses that choice.
34
35 THE CHEAP RUNG IS ALWAYS list_*
36 list_spells / list_conduits / list_root_conduits
37 Names and ids first. Descriptions only for what survives the filter.
38
39 A NOTE ON THIS LESSON'S WORLD
40 ViewSpell and ViewConduit are FRAME-SCOPED (lesson 13), and a
41 freshly opened rift is contracted to no frames - so this lesson
42 maps the ladder off the EXPORTED TYPES rather than off instances.
43 That is not a workaround: THE LADDER IS A PROPERTY OF THE CLASS.
44 You do not need a populated world to see the shape of the surface
45 you will be paying for, which is exactly the point of surveying
46 before you commit.
47
48 The HOST-SCOPED view (get_view_multiframe) needs no frame, so the
49 cheapest rung of all really is callable before you have assigned
50 anything - and this lesson proves that too.
51SURFACE EXERCISED: md.ViewSpell, md.ViewConduit - the describe ladder,
52 list_* enumeration, empty-world coherence
53VERIFY: rides the owner's 3.14t run; asserts are the contract.
54"""
55import melder as md
56
57
58SPELL_LADDER = (
59 "describe_spell_brief",
60 "describe_spell",
61 "describe_spell_detail",
62 "describe_spell_payload",
63)
64
65SPELL_FACETS = (
66 "describe_spell_identity",
67 "describe_spell_source",
68 "describe_spell_origin",
69 "describe_spell_binding",
70 "describe_spell_index",
71 "describe_spell_resolution",
72 "describe_spell_metadata",
73 "describe_spell_research",
74 "describe_spell_class_profile",
75)
76
77CONDUIT_LADDER = (
78 "describe_conduit_brief",
79 "describe_conduit",
80 "describe_conduit_topology",
81 "describe_conduit_inventory",
82 "describe_conduit_relationships",
83 "describe_conduit_crosswalk",
84)
85
86
87def main() -> None:
88 nexus = md.Nexus()
89 system_config = nexus.create_configuration()
90 system_config.with_rift_creation_enabled(True)
91 nexus.activate(system_config)
92
93 rift_config = nexus.create_rift_configuration()
94 rift_config.with_space_type("capability")
95 rift = nexus.create_rift(configuration=rift_config, rift_name="survey")
96 rift.mark_active()
97
98 viewer = rift.space.frame_viewer
99
100 # THE VIEWS ARE FRAME-SCOPED (lesson 13) and this rift is contracted
101 # to none, so we map the surface off the EXPORTED TYPES rather than
102 # off instances. The ladder is a property of the class - you do not
103 # need a populated world to see its shape.
104 assert rift.list_assigned_frame_names() == ()
105 print("no assigned frames - mapping the ladder from the types")
106
107 # THE CHEAP RUNG. Enumeration first - names and ids, nothing more.
108 for cheap in ("list_spells",):
109 assert hasattr(md.ViewSpell, cheap), cheap
110 for cheap in ("list_conduits", "list_root_conduits"):
111 assert hasattr(md.ViewConduit, cheap), cheap
112 print("cheap rung: list_spells / list_conduits / list_root_conduits")
113
114 # But the HOST-SCOPED view needs no frame, so the cheap rung really
115 # is callable right now - proof the survey entry point is reachable
116 # before you have committed to anything.
117 multiframe = viewer.get_view_multiframe()
118 frames = multiframe.list_frame_names()
119 assert isinstance(frames, list)
120 print("host-scoped survey works with no frame bound:", frames)
121
122 # THE LADDER EXISTS, RUNG BY RUNG. Four resolutions for one spell.
123 print()
124 print("ViewSpell resolution ladder:")
125 for rung, verb in enumerate(SPELL_LADDER, start=1):
126 assert hasattr(md.ViewSpell, verb), verb
127 print(f" {rung}. {verb}")
128
129 # NINE FACETS. Ask for one slice instead of the whole record.
130 print()
131 print("ViewSpell per-facet verbs:", len(SPELL_FACETS))
132 for verb in SPELL_FACETS:
133 assert hasattr(md.ViewSpell, verb), verb
134 print(" ", verb.replace("describe_spell_", ""))
135
136 # ViewConduit is built to the same plan.
137 print()
138 print("ViewConduit resolution ladder:")
139 for rung, verb in enumerate(CONDUIT_LADDER, start=1):
140 assert hasattr(md.ViewConduit, verb), verb
141 print(f" {rung}. {verb}")
142
143 # Filters belong on the cheap rung too - narrow BEFORE you describe.
144 for narrowing in ("list_conduits_by_root_id", "list_conduits_by_policy",
145 "is_root_conduit", "get_root_conduit_id"):
146 assert hasattr(md.ViewConduit, narrowing), narrowing
147 print()
148 print("filters live on the cheap rung: narrow first, describe after")
149
150 # The shape is deliberate: strictly more facets than ladder rungs,
151 # because most questions want one slice rather than one more size.
152 assert len(SPELL_FACETS) > len(SPELL_LADDER)
153 print("facets:", len(SPELL_FACETS), "> ladder rungs:", len(SPELL_LADDER))
154
155 print()
156 print("survey at brief, commit at detail - the ladder is a budget")
157 print("a read surface that throws on an empty world cannot survey")
158
159
160if __name__ == "__main__":
161 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.