# Composing a version in the workshop **🔵 Expert · Lesson 30** THE HALF OF A MERGE THAT JOIN REFUSES TO DO, on code the room actually generated. Expert 23 said it outright: "Reconciliation-by- content is not a join concern: compose in the codegen workshop, register the multi-parent result, then join." This is that workshop, and the material is real codegen output - not classes typed into this file. A record that merged content FOR you would be guessing about your source. So melder splits the act in two: you COMPOSE (here), and the record BOOKS the outcome (expert 23). Nothing in between. THE COMPOSITION VERB research_synthesize(base_spell_id, donor_spell_id, take_functions=, take_classes=, stage_ancestry=False) Take named top-level functions/classes from the DONOR's root module, splice them into the BASE's, and hand back the composed source with a full foresight preview. Nothing executes, binds or records - it is a candidate, not a version. SYNTHESIS IS MODULE-GRAIN. The engine says so itself: it "splices ONE version's module world". Each id resolves to its ROOT MODULE text, and `take_functions` / `take_classes` name TOP-LEVEL parts of that module. A METHOD is not a top-level function. Asking for one raises, and the refusal NAMES what the donor actually carries - which is how you discover the grain if you guessed wrong. WHICH IS WHY THIS LESSON GENERATES ITS TWO MODULES. Two classes typed into ONE example file resolve to the SAME module, so every selection is a part replaced by itself and "added" is unreachable - the splice degenerates into a no-op that proves nothing. Real composition needs two module worlds, so the room writes them: validate_codegen -> materialize_codegen -> import -> bind That is the documented loop - materialize's own contract calls binding the class inside the new module the step that "closes the codegen -> synthmodule -> bind -> crystal loop". AND GENERATED CODE IS THE MORE RELIABLE SOURCE, not the exotic one: "synthetic module sources are ALWAYS harvested; user module text rides the opt-in retention lane". The material a room wrote is the material it can always read back. AND THE DIFF DEFAULT IS KIND-AWARE, not a single fallback. research_diff(left, right, strategy=None) With no strategy the room asks what you handed it. Two SPELLS get "structural" - the room's reasoning layer - pinned for them. Two COMPOSITIONS get nothing pinned at all: the room passes no strategy and the engine's own "members" default answers. One verb, two vocabularies, selected by KIND. ("source" is whole-module text, "parts" is per-class/function grain; both are always yours by asking.) A DEFAULT IS A KINDNESS FOR SILENCE, NEVER AN OVERRIDE. Name a strategy and it travels down untouched - an unknown one surfaces the engine's KeyError rather than being quietly answered by a different question than the one asked. THE MINT IS A SEPARATE, ONE-SHOT STAMP research_stage_ancestry([base, donor]) research_clear_staged_ancestry() Staging says "the next FRESH world entry has these parents". It is consumed ONCE and it is ambient, not attached to any particular call. A REDISCOVERY DOES NOT CONSUME IT - identical content re-entering the world is not the synthesized candidate arriving. AND THE STAMP SURVIVES UNTIL USED OR CLEARED. No scope ends it, which is why `clear_staged_ancestry` exists: abandon a composition and you must clear, or the next unrelated bind inherits parents it never had. ## Before you run Use the [Expert guide](../../expert/index.md) 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 ```bash python UX_and_AIX_experiences/04_expert/30_composing_a_version_in_the_workshop.py ``` ```powershell py -3.14t UX_and_AIX_experiences/04_expert/30_composing_a_version_in_the_workshop.py ``` {download}`Download this collection <../../downloads/expert-examples.zip>` · [Source on GitHub](https://github.com/Synaptic724/melder/blob/90d52e0a12cb0743d62568d5a19ce954a54443bc/UX_and_AIX_experiences/04_expert/30_composing_a_version_in_the_workshop.py) ## Public surface validate_codegen / materialize_codegen / research_synthesize / research_stage_ancestry / research_clear_staged_ancestry / research_diff ## Code ```{literalinclude} ../../downloads/04_expert/30_composing_a_version_in_the_workshop.py :language: python :linenos: ``` ## 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](index.md) · [Level guide](../../expert/index.md) ## Related guides - [Compositions, synthesis, and impact](../../expert/compositions.md) - [Complete operational walkthroughs](../../expert/walkthroughs.md)