On this page

Organising lanes after the fact๏ƒ

๐Ÿ”ต Expert ยท Lesson 31

LANES ARE ORGANISED AFTER THE FACT, NOT PLANNED IN ADVANCE. Expert 23 cut branches and joined them. This is the other three verbs - the ones for when you got the shape wrong the first time.

research_attach(lane, onto=, at_spell_id=) re-anchor ancestry research_detach(lane) forget the anchor research_archive(lane) retire a dead end

ANCESTRY IS ORGANISATION, NOT CONTENT. Every one of these moves where a lane SAYS it came from. None of them copies, moves or deletes a version. That separation is why re-organising is cheap and safe: the nodes never move, so a wrong anchor is a wrong label rather than lost work.

ATTACH IS ALL-OR-NOTHING, and it refuses before taking a lock: onto and at_spell_id must both be supplied. There is no "anchor to whatever the tip is" shorthand, because the anchor is the one fact a later join reasons about - a shorthand would let you record a different anchor than you meant.

DETACH IS NOT A DELETE. It removes the anchor, leaving a lane that remembers nothing about where it came from. A detached lane can still be joined, but the join is DIVERGENT by definition - no anchor means nothing for the receiver's tip to agree with - so it needs the same explicit force=True supersede.

ARCHIVE RETIRES A LANE WITHOUT LOSING IT. Residence is permanent: the versions stay resident in the archived container, rediscovery still points at it, and a network snapshot can restore a view that contained it. Archiving hides a dead end from the ACTIVE view; it does not unmake it.

AND THE DEFAULT LANE NEVER ARCHIVES. It is the guaranteed world-entry record - register_spell without a lane records there, and default_lane resolves by well-known name - so a set that archived it could not serve its own default. The refusal is checked at the door rather than discovered later.

THE RECEIVER MOVES BY A NEW VERSION, BOUND THE WAY THE FIRST WAS. Rule is bound under the string category 'Rule' - the address a bare bind of Rule has - with binding name 'organise-rule', and RuleV2 is staged the same way; bind_inactive refuses a version bound any other way (2026-10-25).

Before you run๏ƒ

Use the Expert 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/04_expert/31_organising_lanes_after_the_fact.py
py -3.14t UX_and_AIX_experiences/04_expert/31_organising_lanes_after_the_fact.py

Download this collection ยท Source on GitHub

Public surface๏ƒ

research_create_lane / research_attach / research_detach / research_archive / research_join / research_heads, ResearchSet.lane_names, Conduit.bind_inactive

Code๏ƒ

  1"""
  2TIER: expert (31)
  3GOAL: LANES ARE ORGANISED AFTER THE FACT, NOT PLANNED IN ADVANCE. Expert
  4      23 cut branches and joined them. This is the other three verbs -
  5      the ones for when you got the shape wrong the first time.
  6
  7        research_attach(lane, onto=, at_spell_id=)   re-anchor ancestry
  8        research_detach(lane)                        forget the anchor
  9        research_archive(lane)                       retire a dead end
 10
 11      ANCESTRY IS ORGANISATION, NOT CONTENT. Every one of these moves
 12      where a lane SAYS it came from. None of them copies, moves or
 13      deletes a version. That separation is why re-organising is cheap
 14      and safe: the nodes never move, so a wrong anchor is a wrong label
 15      rather than lost work.
 16
 17      ATTACH IS ALL-OR-NOTHING, and it refuses before taking a lock:
 18      `onto` and `at_spell_id` must both be supplied. There is no
 19      "anchor to whatever the tip is" shorthand, because the anchor is
 20      the one fact a later join reasons about - a shorthand would let you
 21      record a different anchor than you meant.
 22
 23      DETACH IS NOT A DELETE. It removes the anchor, leaving a lane that
 24      remembers nothing about where it came from. A detached lane can
 25      still be joined, but the join is DIVERGENT by definition - no
 26      anchor means nothing for the receiver's tip to agree with - so it
 27      needs the same explicit `force=True` supersede.
 28
 29      ARCHIVE RETIRES A LANE WITHOUT LOSING IT. Residence is permanent:
 30      the versions stay resident in the archived container, rediscovery
 31      still points at it, and a network snapshot can restore a view that
 32      contained it. Archiving hides a dead end from the ACTIVE view; it
 33      does not unmake it.
 34
 35      AND THE DEFAULT LANE NEVER ARCHIVES. It is the guaranteed
 36      world-entry record - `register_spell` without a lane records there,
 37      and `default_lane` resolves by well-known name - so a set that
 38      archived it could not serve its own default. The refusal is checked
 39      at the door rather than discovered later.
 40
 41      THE RECEIVER MOVES BY A NEW VERSION, BOUND THE WAY THE FIRST WAS.
 42      Rule is bound under the string category 'Rule' - the address a
 43      bare bind of Rule has - with binding name 'organise-rule', and
 44      RuleV2 is staged the same way; bind_inactive refuses a version
 45      bound any other way (2026-10-25).
 46SURFACE EXERCISED: research_create_lane / research_attach /
 47                   research_detach / research_archive / research_join /
 48                   research_heads,
 49                   ResearchSet.lane_names, Conduit.bind_inactive
 50VERIFY: RUN GREEN 2026-10-25 on 3.14t, GIL off and on; asserts are the
 51        contract.
 52"""
 53import melder as md
 54
 55
 56FRAME = "organise-world"
 57
 58
 59class Rule:
 60    def __init__(self) -> None:
 61        self.tag = "v1"
 62
 63
 64class RuleV2:
 65    def __init__(self) -> None:
 66        self.tag = "v2"
 67
 68
 69def main() -> None:
 70    crystallizer = md.Crystallizer()
 71    crystallizer.activate(
 72        md.CrystallizerConfigurationBuilder().with_defaults().activate(),
 73    )
 74    research = md.MutationResearch()
 75    configuration = research.create_configuration()
 76    configuration.with_defaults().activate()
 77    research.activate(configuration)
 78
 79    spellbook_configuration = (
 80        md.SpellbookConfiguration(FRAME).with_defaults().finalize()
 81    )
 82    book = md.Spellbook(aetheric_frame=FRAME,
 83                        configuration=spellbook_configuration)
 84    book.configure_aether_frame(
 85        system_state="dynamic",
 86        disposal=None,
 87        disposal_method_names=None,
 88        rift_enabled=True,
 89        ai_native=True,
 90    )
 91    v1 = book.bind(spell=Rule, spellframe="Rule", existence="unique",
 92                   permissions="create", binding_name="organise-rule")
 93    conduit = book.conjure(name="organise-root")
 94
 95    nexus = md.Nexus()
 96    system_configuration = nexus.create_configuration()
 97    system_configuration.with_rift_creation_enabled(True)
 98    system_configuration.with_allowed_target_frame_names([FRAME])
 99    nexus.activate(system_configuration)
100    rift_configuration = nexus.create_rift_configuration()
101    rift_configuration.with_space_type("codegen")
102    rift = nexus.create_rift(configuration=rift_configuration,
103                             rift_name="organiser")
104    rift.mark_active()
105    rift.create_frame_link(FRAME)
106    commands = rift.space.command_system
107    research_set = research.research_set()
108    print("v1 on the default lane:", v1[:12], "...")
109
110    # A lane cut with NO anchor - a perfectly legal shape, and the one
111    # `attach` exists to repair.
112    unanchored = commands.research_create_lane(
113        "unanchored", reason="cut without an anchor on purpose",
114    )
115    assert unanchored["anchor_spell_id"] is None
116    assert len(unanchored["nodes"]) == 0
117    print("cut 'unanchored' -> anchor is None, nodes 0")
118
119    # ATTACH IS ALL-OR-NOTHING and refuses before doing anything.
120    try:
121        commands.research_attach("unanchored", onto="default")
122        raise AssertionError("expected a refusal: anchor is all-or-nothing")
123    except TypeError:
124        print("attach(onto=) without at_spell_id -> TypeError (both or none)")
125
126    # Now anchor it properly, after the fact.
127    commands.research_attach("unanchored", onto="default", at_spell_id=v1,
128                             reason="organising after the fact")
129    print("attach(onto='default', at_spell_id=v1) accepted")
130    print("  ancestry only - no node was copied, moved or created")
131
132    # A clean join is now possible, because the receiver is still at v1.
133    commands.research_join("unanchored", into="default",
134                           reason="anchored, and the receiver has not moved")
135    print("join('unanchored') accepted - re-anchoring made it joinable")
136
137    # DETACH: a second lane, anchored, then deliberately un-anchored.
138    commands.research_create_lane(
139        "forgetful", attach_to="default", attach_at_spell_id=v1,
140        reason="this one will forget where it came from",
141    )
142    commands.research_detach("forgetful", reason="dropping the anchor")
143    print()
144    print("detach('forgetful') - the lane now remembers no origin")
145
146    # Move the receiver so the contrast is honest, then show that a
147    # detached lane joins only as an explicit supersede. The new version
148    # is bound the way the index's first one was.
149    v2 = conduit.bind_inactive(
150        spell=RuleV2,
151        spell_index=conduit.get_spell_by_spell_id(v1).spell_index,
152        spellframe="Rule", binding_name="organise-rule",
153        existence="unique", permissions="create",
154    )
155    print("default moved on:", v2[:12], "...")
156
157    try:
158        commands.research_join("forgetful", into="default")
159        raise AssertionError("expected a refusal: no anchor means divergent")
160    except RuntimeError as error:
161        print("join('forgetful') refused -", str(error)[:100])
162        print("  no anchor means nothing for the tip to agree with, so the")
163        print("  join is divergent BY DEFINITION - not by drift")
164
165    commands.research_join("forgetful", into="default", force=True,
166                           reason="explicit supersede of an unanchored line")
167    print("join(force=True) accepted")
168
169    # ARCHIVE: retire a dead end. It is hidden, not unmade.
170    commands.research_create_lane(
171        "dead-end", attach_to="default", attach_at_spell_id=v1,
172        reason="an experiment that went nowhere",
173    )
174    # OPEN BUT EMPTY IS A REAL STATE. heads() carries the lane with a tip
175    # of None - "absent" and "None" mean different things here.
176    assert commands.research_heads()["dead-end"] is None
177    print()
178    print("'dead-end' is open with tip None - empty, not absent")
179
180    commands.research_archive("dead-end", reason="went nowhere")
181
182    # HIDDEN, NOT UNMADE - and the two reads disagree ON PURPOSE.
183    assert "dead-end" not in commands.research_heads(), "left the active view"
184    assert "dead-end" in research_set.lane_names(), "still exists - no delete"
185    print("archive('dead-end'):")
186    print("  heads()      -> dropped   (OPEN lanes only)")
187    print("  lane_names() -> still there (ALL lanes, any state)")
188    print("  the two reads disagree deliberately, and that gap IS the")
189    print("  difference between hidden and unmade. Residence stays")
190    print("  PERMANENT: the versions remain resident in the archived")
191    print("  container and a network snapshot can restore a view that")
192    print("  contained it")
193
194    # THE DEFAULT LANE NEVER ARCHIVES.
195    try:
196        commands.research_archive("default")
197        raise AssertionError("expected a refusal: default is guaranteed")
198    except RuntimeError as refusal:
199        print()
200        print("archive('default') refused -", str(refusal)[:100])
201        print("  it is the guaranteed world-entry record: register_spell")
202        print("  with no lane records THERE, so a set that archived it")
203        print("  could not serve its own default")
204
205    # A JOIN FINISHES THE SOURCE: both joined lanes are terminal, and the
206    # archived one is retired, so `default` is the only lane left open.
207    open_lanes = commands.research_heads()
208    assert set(open_lanes) == {"default"}, sorted(open_lanes)
209    print()
210    print("open lanes now:", sorted(open_lanes),
211          "- a join finishes its source")
212    print()
213    print("attach, detach, archive - all organisation, none content")
214    print("nodes never move, so a wrong shape is a wrong label, not lost work")
215
216
217if __name__ == "__main__":
218    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 expert examples ยท Level guide

API contracts๏ƒ