On this page
What you cannot see๏
๐ Advanced ยท Lesson 15
THE READ SURFACE REPORTS ITS OWN BLIND SPOTS. Arc C closes on the most unusual thing in the viewer family, and the most useful one if you are an agent.
START FROM THE PROBLEM. You call describe_spell(...) and a field is not there. What does that mean?
(a) the field does not exist for this spell, or (b) it exists and this rift is not allowed to see it.
melder states outright that you cannot tell from the outside:
"VISIBILITY-FILTERED PROJECTION: absence means 'not visible to this rift' OR 'not present', INDISTINGUISHABLE FROM OUTSIDE."
Almost every API in existence stops there and leaves you to guess. For a human that produces a confused afternoon. For an agent it produces a CONFIDENT WRONG ANSWER - "this spell has no source binding" instead of "I was not shown the source binding" - and the agent has no way to know which it said.
SO MELDER SHIPS THE DISAMBIGUATOR.
describe_spell_missing_sections(...) ViewSpell describe_conduit_missing_sections(...) ViewConduit describe_missing_surface(...) ViewFrame / FrameViewer
The spell one describes itself as "THE WITHHELD-SECTION PROBE: it computes every payload field name and subtracts the visible ones, so it reports the NAMES of sections you cannot read. THIS IS HOW YOU TELL 'HIDDEN' FROM 'EMPTY' WITHOUT THE CONTENTS."
READ THAT LAST CLAUSE AGAIN - IT IS THE WHOLE DESIGN. You learn the SHAPE of your blindness without breaching it. The contract says "does not expose hidden payload bodies". So the probe is safe to ship to a low-authority room: it can honestly say "there are three sections here you may not read" without reading them.
That is what makes this different from an error message. A refusal tells you that you were stopped. This tells you WHAT you were stopped from, by name, without stopping being enforced any less.
VISIBLE AND MISSING ARE COMPLEMENTS describe_visible_surface() what I can see right now describe_missing_surface() what I cannot Together they partition the world. Either alone is half an answer.
AND ONE ANTI-FOOTGUN WORTH STEALING Every one of these takes frame_name, and it is NOT a selector:
"frame_name is an ASSERTION, not a selector - when supplied it must match the bound frame or the call raises."
A parameter shaped like a filter that is really a guard. You cannot accidentally read a different frame than the one you think you are holding; saying the wrong name is an error, not a surprise result.
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/15_what_you_cannot_see.py
py -3.14t UX_and_AIX_experiences/03_advanced/15_what_you_cannot_see.py
Public surface๏
describe_visible_surface / describe_missing_surface, describe_spell_missing_sections, describe_conduit_missing_sections
Code๏
1"""
2TIER: advanced (15)
3GOAL: THE READ SURFACE REPORTS ITS OWN BLIND SPOTS. Arc C closes on the
4 most unusual thing in the viewer family, and the most useful one if
5 you are an agent.
6
7 START FROM THE PROBLEM. You call describe_spell(...) and a field is
8 not there. What does that mean?
9
10 (a) the field does not exist for this spell, or
11 (b) it exists and this rift is not allowed to see it.
12
13 melder states outright that you cannot tell from the outside:
14
15 "VISIBILITY-FILTERED PROJECTION: absence means 'not visible to
16 this rift' OR 'not present', INDISTINGUISHABLE FROM OUTSIDE."
17
18 Almost every API in existence stops there and leaves you to guess.
19 For a human that produces a confused afternoon. For an agent it
20 produces a CONFIDENT WRONG ANSWER - "this spell has no source
21 binding" instead of "I was not shown the source binding" - and the
22 agent has no way to know which it said.
23
24 SO MELDER SHIPS THE DISAMBIGUATOR.
25
26 describe_spell_missing_sections(...) ViewSpell
27 describe_conduit_missing_sections(...) ViewConduit
28 describe_missing_surface(...) ViewFrame / FrameViewer
29
30 The spell one describes itself as "THE WITHHELD-SECTION PROBE: it
31 computes every payload field name and subtracts the visible ones, so
32 it reports the NAMES of sections you cannot read. THIS IS HOW YOU
33 TELL 'HIDDEN' FROM 'EMPTY' WITHOUT THE CONTENTS."
34
35 READ THAT LAST CLAUSE AGAIN - IT IS THE WHOLE DESIGN.
36 You learn the SHAPE of your blindness without breaching it. The
37 contract says "does not expose hidden payload bodies". So the probe
38 is safe to ship to a low-authority room: it can honestly say "there
39 are three sections here you may not read" without reading them.
40
41 That is what makes this different from an error message. A refusal
42 tells you that you were stopped. This tells you WHAT you were
43 stopped from, by name, without stopping being enforced any less.
44
45 VISIBLE AND MISSING ARE COMPLEMENTS
46 describe_visible_surface() what I can see right now
47 describe_missing_surface() what I cannot
48 Together they partition the world. Either alone is half an answer.
49
50 AND ONE ANTI-FOOTGUN WORTH STEALING
51 Every one of these takes frame_name, and it is NOT a selector:
52
53 "`frame_name` is an ASSERTION, not a selector - when supplied it
54 must match the bound frame or the call raises."
55
56 A parameter shaped like a filter that is really a guard. You cannot
57 accidentally read a different frame than the one you think you are
58 holding; saying the wrong name is an error, not a surprise result.
59SURFACE EXERCISED: describe_visible_surface / describe_missing_surface,
60 describe_spell_missing_sections,
61 describe_conduit_missing_sections
62VERIFY: rides the owner's 3.14t run; asserts are the contract.
63"""
64import melder as md
65
66
67def main() -> None:
68 nexus = md.Nexus()
69 system_config = nexus.create_configuration()
70 system_config.with_rift_creation_enabled(True)
71 nexus.activate(system_config)
72
73 # A STATIC room on purpose - the lower-authority kind (lesson 11).
74 # Blind spots are the point of this lesson, so pick the room that has
75 # more of them.
76 rift_config = nexus.create_rift_configuration()
77 rift_config.with_space_type("static")
78 rift = nexus.create_rift(configuration=rift_config, rift_name="restricted")
79 rift.mark_active()
80
81 viewer = rift.space.frame_viewer
82
83 # THE FAMILY EXISTS AT EVERY LEVEL. That consistency is the point -
84 # you never have to wonder whether this particular view can tell you
85 # what it is hiding. Checked on the TYPES, because the frame-scoped
86 # views cannot be built without an assigned frame (lesson 13).
87 print("the withheld-section probes:")
88 probes = {
89 "ViewSpell.describe_spell_missing_sections":
90 (md.ViewSpell, "describe_spell_missing_sections"),
91 "ViewConduit.describe_conduit_missing_sections":
92 (md.ViewConduit, "describe_conduit_missing_sections"),
93 "ViewFrame.describe_missing_surface":
94 (md.ViewFrame, "describe_missing_surface"),
95 "FrameViewer.describe_missing_surface":
96 (md.FrameViewer, "describe_missing_surface"),
97 }
98 for label, (owner_type, verb) in probes.items():
99 assert hasattr(owner_type, verb), label
100 print(" ", label)
101
102 # AND THEIR COMPLEMENTS. Visible + missing is the whole world.
103 print()
104 print("and the visible half:")
105 for owner_type in (md.ViewFrame, md.FrameViewer):
106 assert hasattr(owner_type, "describe_visible_surface")
107 print(" ", owner_type.__name__ + ".describe_visible_surface")
108
109 # NOW THE PART THAT SURPRISED ME, AND IT BELONGS IN THIS LESSON MORE
110 # THAN ANYWHERE ELSE.
111 #
112 # These reads are FRAME-SCOPED and this rift is contracted to no
113 # frames - so asking "what am I not seeing?" REFUSES rather than
114 # answering "everything". Which is the correct call: with no frame
115 # bound there is no surface to compare against, and a cheerful empty
116 # dict would be a lie shaped like an answer.
117 assert rift.list_assigned_frame_names() == ()
118 print()
119 print("assigned frames:", rift.list_assigned_frame_names())
120
121 for verb in ("describe_visible_surface", "describe_missing_surface"):
122 # No frame name: refused by the SIGNATURE now (2026-08-02 fix).
123 try:
124 getattr(viewer, verb)()
125 raise AssertionError(f"{verb} should require a frame name")
126 except TypeError as error:
127 print(f" {verb:26s} requires a frame name: {error}")
128
129 # A frame name this rift is not contracted to: refused by the
130 # RESOLVER. Naming a world you do not hold is not a quiet empty.
131 try:
132 getattr(viewer, verb)(frame_name="never-assigned")
133 raise AssertionError(f"{verb} should refuse an unheld frame")
134 except Exception as error:
135 print(f" {verb:26s} refused an unheld frame:",
136 type(error).__name__)
137
138 print()
139 print("no frame bound, no blind-spot report - and refusing is right:")
140 print("an empty answer here would be a lie shaped like an answer")
141
142 # NAMES, NOT BODIES. The probe is safe precisely because it withholds
143 # the contents it is telling you about - so it can ship to a room that
144 # is not allowed to read them.
145 print()
146 print("the probe names what it withholds; it never hands over bodies")
147
148 print()
149 print("absence is ambiguous - 'hidden' and 'empty' look identical")
150 print("so melder ships the disambiguator, and keeps the ACL intact")
151
152
153if __name__ == "__main__":
154 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.