On this page

Preview, stage, and govern structural change๏ƒ

Prerequisites: research, codegen, and structural admission. Begin with the existing version's residency, source, and impact. research_preview can combine a candidate analysis with the selected frame's codegen verdict before any candidate is bound.

The foresight example checks that preview leaves research heads unchanged and the original pricing object still returns its original result. A malformed candidate returns parse information that the caller can inspect.

For application checks at registration itself, use the bind-hook review pipeline. Its pre callbacks inspect the supplied reference, activation annotates the new Spell, and post observes the registered result.

Staging is not promotion๏ƒ

bind_inactive places a candidate into the existing SpellIndex while the selected member remains unchanged, and returns the candidate's spell_id. Expert 17 asserts the member set, unchanged selection, and unchanged resolved result.

The candidate is bound the way the index's first version was: the same kind of spellframe (none, a string category or a Protocol) and the same address (the spellframe's name, or a bare class's own name, and the binding name). bind_inactive refuses any other binding before it registers anything, and add_to_spell_index refuses to move a version into an index bound another way. So a notch never moves the address, and a meld by the address builds whichever version is selected. Versions that carry different class names are bound under one spellframe category from the first version on; expert 17 does that and shows a bare staging refused.

Promotion is notch_spell(spell_index=..., spell_id=...) given that spell_id: the candidate becomes the selected member and the next meld builds it, and a notch back by the previous spell_id restores the old version, which stayed parked. Expert 17 runs the whole loop on public calls, as does the README's sketch. A lookup by spell_id is exact: get_spell_by_spell_id returns the version that spell_id names, parked or active, and the version an index has active is a lookup by the index, get_spell_by_index_id. The calls that build nothing follow the same rule: has_live_creation(spell=...), describe_live_creation_status(spell=...) and purge(spell_id=...) given a spell_id answer for that version, parked or active, so a parked version's objects can be checked or retired without a notch back; meld builds only the selected member. notch_spell refuses a version of another index, or one another Spellbook owns, before it changes anything, and it refuses an address another spell holds: a version split off into an index of its own keeps its binding, so it can be notched active there only once its old index no longer serves that address. add_to_spell_index and remove_from_spell_index take spell_id= the same way, to move a parked candidate onto another index bound the same way or out into one of its own.

Keep history and code reconciliation distinct๏ƒ

An anchored research lane starts empty. A clean join checks its relation to the receiver's current tip. A forced join records explicit supersede; it does not merge source code. Compose and evaluate the candidate first, then record the chosen outcome through the applicable public operation.

Archive hides a lane from the active view while retaining its history. It is not runtime object disposal. Keep deliberate version retirement and application cleanup separate from lane organization.

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    # 1. RECORD AND CUSTODY FIRST. A world built before these are live is
  3    #    a world neither of them ever saw.
  4    crystallizer = md.Crystallizer()
  5    crystallizer.activate(
  6        md.CrystallizerConfigurationBuilder().with_defaults().activate(),
  7    )
  8    research = md.MutationResearch()
  9    research_configuration = research.create_configuration()
 10    research_configuration.with_defaults().activate()
 11    research.activate(research_configuration)
 12    assert crystallizer.activated and research.activated
 13    print("custody recording:", crystallizer.activated,
 14          " research live:", research.activated)
 15
 16    # 2. NOW build the world. The bind auto-records because research was
 17    #    already up - had we activated afterwards, nothing would have
 18    #    been recorded and no foresight would have been possible.
 19    # A RECORDED WORLD MUST BE BORN CONFIGURED. With custody active, a
 20    # dynamic conjure REFUSES if any bind ran before the configuration
 21    # was finalized - the profile record and default bootstrap would
 22    # otherwise durably persist binds made against unsettled config.
 23    spellbook_configuration = (
 24        md.SpellbookConfiguration(FRAME).with_defaults().finalize()
 25    )
 26    book = md.Spellbook(aetheric_frame=FRAME,
 27                        configuration=spellbook_configuration)
 28    # AND THE FRAME POSTURE GOES BEFORE THE BIND TOO, for a DIFFERENT
 29    # reason: a plain bind only auto-records `if self._is_dynamic_posture()`,
 30    # which reads the FRAME configuration and is answerable before conjure.
 31    # Bind into a not-yet-dynamic frame and the spell is never declared -
 32    # no residency, no foresight, and no error either, because research
 33    # bookkeeping never gates a bind.
 34    book.configure_aether_frame(
 35        system_state="dynamic",
 36        disposal=None,
 37        disposal_method_names=None,
 38        rift_enabled=True,
 39        ai_native=True,
 40    )
 41    spell_id = book.bind(
 42        spell=PriceRule, existence="unique", permissions="create",
 43        binding_name="foresight-rule",
 44    )
 45    conduit = book.conjure(name="foresight-root")
 46    live = conduit.meld("PriceRule", binding_name="foresight-rule")
 47    assert live.apply(4) == 40
 48    print()
 49    print("world up; PriceRule.apply(4) ->", live.apply(4))
 50    print("spell_id:", spell_id[:12], "...")
 51
 52    # 3. A codegen room pointed at it.
 53    nexus = md.Nexus()
 54    system_configuration = nexus.create_configuration()
 55    system_configuration.with_rift_creation_enabled(True)
 56    system_configuration.with_allowed_target_frame_names([FRAME])
 57    nexus.activate(system_configuration)
 58    rift_configuration = nexus.create_rift_configuration()
 59    rift_configuration.with_space_type("codegen")
 60    rift = nexus.create_rift(configuration=rift_configuration,
 61                             rift_name="foresight")
 62    rift.mark_active()
 63    rift.create_frame_link(FRAME)
 64    commands = rift.space.command_system
 65
 66    # 4. WHAT DOES THE EXISTING VERSION TOUCH, RIGHT NOW?
 67    # `spell_id` is KEYWORD-ONLY here, and so is `module_name` - the verb
 68    # answers about exactly ONE center per call, so it will not let you
 69    # pass a bare identifier and leave which-kind-of-center to inference.
 70    radius = commands.research_impact(spell_id=spell_id)
 71    print()
 72    print("research_impact(existing) -> keys:", sorted(radius)[:6], "...")
 73    print("  the CURRENT blast radius, joined with research residency")
 74
 75    # 5. THE FORESIGHT CALL. Snapshot the record first so we can prove
 76    #    the preview did not touch it.
 77    heads_before = commands.research_heads()
 78
 79    preview = commands.research_preview(
 80        CANDIDATE,
 81        against_spell_id=spell_id,
 82        frame_name=FRAME,
 83    )
 84    for key in ("candidate_sha256", "module_name", "parse_error",
 85                "defines", "import_roots", "diff", "impact",
 86                "against_spell_id"):
 87        assert key in preview, key
 88    print()
 89    print("research_preview ->", len(preview), "keys")
 90    print("   parse_error :", preview["parse_error"])
 91    print("   defines     :", preview["defines"])
 92    print("   import_roots:", preview["import_roots"] or "(none)")
 93    print("   candidate   :", str(preview["candidate_sha256"])[:12], "...")
 94    print("   against     :", str(preview["against_spell_id"])[:12], "...")
 95    assert preview["parse_error"] is None
 96    assert preview["against_spell_id"] == spell_id
 97    print("  it read the candidate's AST - a class defined, no imports -")
 98    print("  diffed it against the version it would replace, and priced")
 99    print("  the replacement, all without running a line")
100
101    # 6. AND THE ROOM'S VERDICT CAME ALONG, because frame_name was given.
102    print()
103    print("frame_name folded the permission question in:")
104    print("  'may I' and 'what would happen' answered in ONE call")
105
106    # 7. THE PROOF. Nothing executed, bound, or recorded.
107    heads_after = commands.research_heads()
108    assert heads_after == heads_before, (
109        "research_preview must not move the record - it is foresight, "
110        "not a dry-run that half-commits"
111    )
112    still = conduit.meld("PriceRule", binding_name="foresight-rule")
113    assert still.apply(4) == 40
114    print("record heads: IDENTICAL before and after the preview")
115    print("live object : still the old rule ->", still.apply(4))
116    print("  'nothing executes, binds, or records' - checked, not trusted")
117
118    # 8. A CANDIDATE THAT DOES NOT PARSE STILL ANSWERS.
119    broken = commands.research_preview(BROKEN, frame_name=FRAME)
120    assert broken["parse_error"] is not None
121    print()
122    print("a candidate that does not parse ->")
123    print("   parse_error:", str(broken["parse_error"])[:60])
124    print("  same payload shape, populated honestly. An agent's generator")
125    print("  emits garbage sometimes, and a foresight tool that raised on")
126    print("  garbage would fail exactly when it is most needed")
127
128    print()
129    print("ask what it WOULD do, then decide - and the asking is free")
130    print("activate record and custody BEFORE you build, or there is")
131    print("nothing to have foresight about")

Runnable examples๏ƒ

All expert examples ยท Level contents ยท Full contents

Canonical page source