On this page
- Spell
SpellSpell.cleanup()Spell.emit_cache()Spell.emit_cache_file()Spell.keySpell.is_existing_creationSpell.is_class_spellSpell.is_method_spellSpell.is_lambda_spellSpell.has_existing_objectSpell.owner_conduit_infoSpell.requirementsSpell.symbolic_graphSpell.resolution_frameSpell.validation_result_phase4Spell.validation_result_phase6Spell.validatedSpell.is_brokenSpell.invalidate_spell()Spell.system_stateSpell.mutation_overrideSpell.has_mutation_overrideSpell.apply_mutation_override()Spell.clear_mutation_override()
Spell๏
Use md.Spell from the public package namespace.
- class Spell(spell: Any, spell_index: SpellIndex, spellframe: Any | None, binding_name: str | None, spell_name: str, existence: Existence, spell_type: SpellType, spell_id: str, permissions: Permissions, aetheric_frame: str, spellbook: Spellbook, profile: Any | None = None, existing_object: object | None = None, disposal_method_names: list[str] | None = None, *args: Any, **kwargs: Any)[source]๏
Internal
Represents one registered spell inside the Melder runtime.
A Spell is the canonical bind-time runtime record for one class, function, lambda, or existing object registration. It keeps the spell's structural identity, lifecycle policy, access policy, reflective profile, build-time artifacts, spell-local runtime helpers, and ownership metadata together so the rest of Melder can reason about one stable object instead of a loose bundle of values.
Contract:
Wraps exactly one registered spell target plus its SpellIndex lineage/version record.
Owns spell-local mutable runtime state such as hooks, dependency/build artifacts, the spell-owned CreationContextFactory, the spell-owned CreationContext, execution-plan dispatch-route metadata, and mutation overlays.
Does not validate bind-time inputs by itself; upstream bind/examiner stages are expected to hand it already-validated configuration.
Uses an internal RLock to guard multi-field configuration and cleanup transitions.
Becomes unusable after cleanup() completes; later live-object methods are expected to fail through check_cleaned().
Disposal metadata is established once at bind. The ordered list, presence flag, and bind-time SHA describe that same policy. Post-creation mutation is unsupported; this class adds no copying or mutation guards.
Core Responsibilities:
Holds an immutable reference to the object (function/class/instance) it represents.
Tracks configuration data: type, binding profile (if attached), spellframe, ownership, and hooks.
Defines dependency DAGs for invocation and construction (via external DAG / resolution pipelines).
Manages permission control via the Permissions enum.
Enables hook-based lifecycle support (pre, activation, post).
Acts as a source of truth for spell identity and access.
Stores bind-time resolved disposal metadata (matched method names + boolean flag).
Tracks whether runtime resolution is still required before the first context build.
Caches the Phase 11 execution-plan dispatch-route hint used by current runtime path selection.
Permissions (Permissions enum):
read: Allows other conduits to use the spell as-is, but not modify or recreate it.
create: Allows other conduits to instantiate or construct new versions.
block: Prevents external access. Internal owner-conduit access is still allowed.
Key Concepts:
Each spell has a unique SHA256 spell_id, generated from its bind-time fingerprint.
spellframe distinguishes the context it was declared in (e.g., Protocol, class, or string frame).
Spells may be cleaned (cleanup()), after which modification is disallowed.
Dependency graphs and resolution profiles are produced by the Resolution / Meld pipeline, not by this class directly.
Permissions are enforced during conduit contract evaluation.
- Parameters:
spell (Any) -- The actual object to register (function, class, lambda, or existing instance).
spell_index (SpellIndex) -- Versioned identity for this spell (current + historical fingerprints).
spellframe (Optional[Any]) -- Frame context (usually a Protocol, class, or string) to scope the spell's identity.
binding_name (Optional[str]) -- The logical name this spell is bound to (e.g., "database", "engine"). Normalized as part of the internal key via SpellInputUtils. Maybe None for unnamed/default bindings.
spell_name (str) -- The actual internal name of the object or callable (for display/debugging).
existence (Existence) -- The spell's lifecycle policy (unique, shared, etc.).
spell_type (SpellType) -- Indicates if the spell is a class, method, lambda, or existing creation, and whether it participates in spellframes and/or binding names.
spell_id (str) -- Unique identifier derived from object fingerprinting (SHA256).
permissions (Permissions) -- Defines access control level for borrowing, invoking, or recreating this spell.
aetheric_frame (str) -- Logical Aether frame / namespace this spell was registered under.
profile (Optional[Any]) --
Optional reflective profile associated with this spell.
Currently:
The Bind pipeline finishes by attaching a combined general or detailed spell profile here.
Those combined profiles still expose the underlying binding and resolution artifacts for downstream consumers.
Legacy usage expecting raw profile types should treat this field as an opaque introspection artifact and normalize it first.
existing_object (Optional[object]) -- Optional pre-instantiated object to attach to the spell (EXISTING_CREATION* types). For factory-like spells (class/method/lambda), this is usually None.
spellbook (Spellbook) -- Back-reference to the owning Spellbook. This is a required live-owner contract used for internal coordination, graph wiring, diagnostics, and spell-system-state attachment.
kwargs (args and) -- Arbitrary tags and metadata for internal use or future extensions.
Threading / Concurrency:
'_Lock' guards internal multi-field mutation.
Spell-owned runtime context publication uses _creation_context_switch so only one builder wins publication at a time.
Higher-level conduit/spellbook orchestration still owns system-level concurrency decisions; this class only protects its own local state.
Lifecycle / Cleanup:
Spell owns its spell compiler artifact foundation, spell-owned CreationContextFactory, spell-owned CreationContext, hook lists, dependency/build artifacts and cached execution-plan dispatch-route metadata.
Conduit ownership can be restamped later, which invalidates the spell-owned CreationContext and rebuilds the spell-owned factory.
cleanup() is deterministic, best-effort for owned child cleanup, and clears references to prevent reuse-after-clean.
- Registration:
MELDER KERNEL - guarded (internal manifest). Melder constructs every Spell during Bind; a user never asks Melder to inject one, so bind(Spell) is the category error the guard refuses. access=public is deliberate and orthogonal to the guard: agents RECEIVE spells from bind() and from viewer/examination surfaces and read their identity, existence, and permissions - they simply do not construct or re-bind them.
- Subsystem Context:
The unit of currency of the spellbook subsystem. Bind produces one Spell (paired with its SpellIndex lineage/version record) from a user target; Spellbook registers it into its owned/contracted maps and spell-id caches and registers the lineage into SpellSystemStates. Downstream, the SpellCompiler keys every phase artifact on this spell (by spell_index.selected_spell_id) and Meld reads it to choose reuse-vs-construct. It hands structural identity to SpellIndex, build/plan artifacts to the SpellCompiler, and its Permissions to ConduitWard contract evaluation.
- System Context:
Lives in the Spellbook layer of the DGR boot order (Aether|AetherUtilitySystem -> Crystallizer -> MutationResearch -> Nexus -> AethericFrame -> Spellbook -> Conduit|Ward). Created at bind time - after a frame exists, before conjure - and is the object every later layer operates on per-spell: SpellCompiler phases 1-11, SpellSystemStates validity, ChangeControl dirty-root gating, and Meld resolution into live instances via Creations. It sits between the Spellbook that owns it and the Conduit/Meld layer that resolves it.
Notes
This class is never used directly by users. It is created during bind() and registered into the Spellbook and Aether.
Internal mutation after cleaning is disallowed.
Dependency graphs, resolution frames, and resolution profiles are produced by the Resolution / Meld layer; Spell itself does not execute resolution.
AGENT_ACCESS: public
- AGENT_PURPOSE:
access: public. One registered binding: identity, existence, permissions, spellframe, hooks. You receive spells from bind and from viewer surfaces; you do not construct them.
- cleanup() None[source]๏
Release the spell-owned runtime state and permanently retire this Spell.
- Purpose:
Deterministically tear down the spell-local runtime surface so later code cannot keep using stale build artifacts, runtime contexts, or owner references after the spell leaves service.
Contract:
Idempotent: repeated calls become no-ops after _cleaned flips.
Thread-safe: acquires _lock, re-checks _cleaned, and then performs teardown under the guarded section.
Best-effort child cleanup: owned child cleanup failures are swallowed so teardown still reaches the final cleared state.
Clears hooks, metadata, dependency/build artifacts, execution-plan metrics, spell-owned factory/context state, conduit ownership state, spellbook references, and reflective profile state.
Sets _cleaned before the guarded section exits, then drops the _lock reference itself after the teardown completes.
Deletes the disposal-name reference without clearing its list; creation entries may still retain that established metadata.
Runtime resolution and instance lifecycle remain owned by the Resolution / Meld layer, not by this class.
- Returns:
None.
- emit_cache() bool[source]๏
Public API
Emit this spell's current cache payload through its owning Spellbook.
- Purpose:
Provide one spell-facing cache export entrypoint without moving cache ownership or file mutation into CreationContext.
Contract:
Returns early when spell-level cache policy is disabled.
Delegates the real cache update to the owning Spellbook.
Requires the spell to still have a live owning Spellbook.
- Returns:
True when the spell emitted a cache payload, otherwise False.
- Return type:
bool
- Raises:
RuntimeError -- If the spell no longer has an owning Spellbook.
- emit_cache_file() bool[source]๏
Public API
Emit the Spellbook-owned cache file for this spell's current cache state.
- Purpose:
Provide one spell-facing entrypoint for forcing the current Spellbook-owned in-memory cache state to disk.
Contract:
Returns early when spell-level cache policy is disabled.
Delegates the real file emit to the owning Spellbook.
Requires the spell to still have a live owning Spellbook.
- Returns:
True when the Spellbook cache file was emitted, otherwise False.
- Return type:
bool
- Raises:
RuntimeError -- If the spell no longer has an owning Spellbook.
- property key: tuple[str, str]๏
Internal
Return the canonical (frame_key, binding_key) lookup tuple.
Contract:
Always reflects the bind-time normalized key produced by SpellInputUtils.make_spell_key_from_parts(...).
Read-only at the Spell layer; callers must not mutate key semantics after bind time.
- Returns:
Canonical Spellbook dictionary key for this spell.
- Return type:
tuple[str, str]
- property is_existing_creation: bool๏
Whether this spell represents an existing, pre-created object.
Contract:
Derived ONCE from spell_type during __init__ and never recomputed; it is a bind-time fact, not runtime state.
Part of a strict four-way partition with is_class_spell, is_method_spell and is_lambda_spell: the four families cover all 14 SpellType members with no overlap, so for any spell EXACTLY ONE of them is True. Branching on all four without a fallback is safe and total.
Answers "did the user hand us the object?", which is distinct from has_existing_object - that one asks whether the object is still attached right now.
- Threading:
Unsynchronized read of an immutable bool; safe from any thread.
- Returns:
True only for EXISTING_CREATION* spell types.
- Return type:
bool
- property is_class_spell: bool๏
Whether this spell represents a class-backed factory registration.
Contract:
Derived ONCE from spell_type during __init__; bind-time fact.
Covers the four SPELL* members. This is the FACTORY family: melding constructs an instance per the spell's Existence policy, as opposed to is_existing_creation where the instance already exists.
Exactly one of the four family flags is True for any spell (see is_existing_creation for the full partition).
- Threading:
Unsynchronized read of an immutable bool; safe from any thread.
- Returns:
True only for SPELL* spell types.
- Return type:
bool
- property is_method_spell: bool๏
Whether this spell represents a non-lambda method or function registration.
Contract:
Derived ONCE from spell_type during __init__; bind-time fact.
Covers the four named METHOD* members and EXCLUDES the three LAMBDA_METHOD* members, which report through is_lambda_spell. The split exists because a lambda has no stable qualname to bind against, so lambda variants always carry a binding name or spellframe.
Exactly one of the four family flags is True for any spell (see is_existing_creation for the full partition).
- Threading:
Unsynchronized read of an immutable bool; safe from any thread.
- Returns:
True only for non-lambda METHOD* spell types.
- Return type:
bool
- property is_lambda_spell: bool๏
Whether this spell represents one of the lambda-backed method spell variants.
Contract:
Derived ONCE from spell_type during __init__; bind-time fact.
Covers the three LAMBDA_METHOD* members. Every one of them carries a binding name, a spellframe, or both - there is no bare LAMBDA_METHOD member, because an anonymous function supplies no usable identity of its own to bind against.
Exactly one of the four family flags is True for any spell (see is_existing_creation for the full partition).
- Threading:
Unsynchronized read of an immutable bool; safe from any thread.
- Returns:
True only for lambda METHOD* spell types.
- Return type:
bool
- property has_existing_object: bool๏
Whether this spell currently holds a concrete user-provided object.
Contract:
Meaningful only for EXISTING_CREATION* spell types.
Returns False for factory-style spell types even if they later create runtime instances through conduits.
- Returns:
True when user_created_object is currently attached.
- Return type:
bool
- property owner_conduit_info: tuple[str | None, str | None]๏
Return the current conduit ownership tuple for this spell.
Contract:
Both halves start None and are populated together when the owning conduit stamps ownership, which happens after conjure - never at bind time. (None, None) therefore means "not yet owned", not "error".
The name half is a convenience label and may be None even once the id is set, for conduits created without an explicit name.
- Threading:
Reads the two attributes separately WITHOUT holding self._lock, so the pair is not snapshotted atomically. A read racing an ownership stamp can observe a mixed tuple (new id, stale name). Callers that need a coherent pair must hold the spell lock via the with spell: context manager.
- Returns:
(owner_conduit_id, owner_conduit_name) when ownership has been stamped, otherwise (None, None).
- Return type:
tuple[Optional[str], Optional[str]]
- property requirements: SpellRequirements | None๏
Phase 1 artifact for this spell, if it has been computed.
This is populated by the compiler artifact during structural phase execution.
Contract:
PHASE-GATED PROBE. None means Phase 1 has not produced this artifact yet - either the structural phases have not run, or the artifact was invalidated and reset. It is never an error value, so this property does not raise for an un-run phase.
A read-through onto the spell-owned SpellCompilerArtifact. The Spell is the public face of that artifact; the artifact itself is internal.
The returned object is live, not a copy. A subsequent recompilation can replace or mutate it underneath the caller.
- Threading:
Unsynchronized read-through; a snapshot of a reference that compilation can swap concurrently.
- Returns:
- Phase 1 requirements, or None before the
structural phases have run for this spell.
- Return type:
Optional[SpellRequirements]
- property symbolic_graph: SpellSymbolicGraph | None๏
Phase 2 symbolic graph for this spell, if it has been computed.
This is populated by the compiler artifact during structural phase execution.
Contract:
PHASE-GATED PROBE; None means Phase 2 has not produced this artifact yet, or it was reset by an invalidation. Not an error.
Phase 2 consumes Phase 1, so a non-None graph implies requirements was populated at the time the graph was built - but not that it is still populated now, since invalidation can clear artifacts independently.
Read-through onto the spell-owned SpellCompilerArtifact; returns the live object, not a copy.
- Threading:
Unsynchronized read-through; snapshot only.
- Returns:
- The Phase 2 symbolic graph, or None before
Phase 2 has run.
- Return type:
Optional[SpellSymbolicGraph]
- property resolution_frame: Any๏
Phase 3 local resolution frame / DAG for this spell, if it has been computed.
This is populated by the compiler artifact during structural phase execution. Concrete type is intentionally opaque here; callers should treat it as an internal resolution artifact.
Contract:
PHASE-GATED PROBE; None means Phase 3 has not produced this artifact yet, or it was reset. Not an error.
The Any return type is DELIBERATE, not missing typing. The concrete resolution/DAG type is internal and free to change; treat the value as an opaque handle to pass back into melder, and do not branch on its structure.
Read-through onto the spell-owned SpellCompilerArtifact; returns the live object, not a copy.
- Threading:
Unsynchronized read-through; snapshot only.
- Returns:
The Phase 3 resolution frame, or None before Phase 3 has run.
- Return type:
Any
- property validation_result_phase4: SpellValidationResult | None๏
Phase 4 validation result for this spell, if it has been computed.
This is populated by the compiler artifact during structural phase execution.
Contract:
THIS IS THE DISCRIMINATOR for the validated / is_broken booleans. Those two are False both before Phase 4 runs and after a failing verdict; this property is None in the first case and non-None in the second, so it is the only way to tell "not checked" from "checked".
STRUCTURAL verdict only - it judges the spell in isolation. Conduit-scoped judgement lives in validation_result_phase6, and a spell can pass Phase 4 and still fail Phase 6.
Read-through onto the spell-owned SpellCompilerArtifact; returns the live object, not a copy.
- Threading:
Unsynchronized read-through; snapshot only.
- Returns:
- The structural (Phase 4) verdict, or None
if Phase 4 has not run for this spell.
- Return type:
Optional[SpellValidationResult]
- property validation_result_phase6: SpellSystemValidationState | None๏
Phase 6 validation result for this spell, if it has been computed.
This is populated by the compiler artifact during conduit-scoped validation.
Contract:
CONDUIT-SCOPED verdict, unlike the structural Phase 4 result. None here is expected for a bound-but-never-conjured spell, because Phase 6 runs as part of conduit-scoped validation rather than at bind time.
Passing Phase 4 does not imply Phase 6 will pass: a spell can be structurally sound and still be unsatisfiable in the conduit it is asked to live in (missing dependency, permission refusal).
None is not an error and this property does not raise.
Read-through onto the spell-owned SpellCompilerArtifact; returns the live object, not a copy.
- Threading:
Unsynchronized read-through; snapshot only.
- Returns:
- The system (Phase 6) verdict, or None
if Phase 6 has not run for this conduit.
- Return type:
Optional[SpellSystemValidationState]
- property validated: bool๏
Whether Phase 4 validation currently considers this spell valid.
Contract:
False IS AMBIGUOUS. It means either "Phase 4 has not run" or "Phase 4 ran and the spell did not pass". The flag alone cannot distinguish them, because it is initialized False and is reset to False whenever the artifact is invalidated.
To tell the two apart, read validation_result_phase4: None means the phase has not produced a verdict; a non-None result means the verdict is real and validated reflects it.
Never raises for an un-run phase; absence is reported as False, not as an error.
- Threading:
Unsynchronized read of the compiler artifact's flag. It is a snapshot; a concurrent revalidation can flip it immediately after this returns.
- Returns:
False until Phase 4 validation has populated the compiler artifact.
- Return type:
bool
- property is_broken: bool๏
Whether validation currently classifies this spell as broken or unsafe.
Contract:
False IS AMBIGUOUS in the same way as validated: it is the initial value AND the reset value, so an unvalidated spell and a validated-healthy spell both report False.
is_broken is NOT the negation of validated. A spell that has never been validated reports validated=False AND is_broken=False simultaneously. Do not treat not is_broken as "safe to use".
The honest health check is: validation_result_phase4 is not None (a verdict exists) AND validated (the verdict passed).
- Threading:
Unsynchronized read of the compiler artifact's flag; a snapshot only.
- Returns:
False until Phase 4 validation has populated the compiler artifact.
- Return type:
bool
- invalidate_spell(change_reason: SpellStateChangeReason | None = None) None[source]๏
Invalidate this spell for a full next-meld rebuild.
- Purpose:
Provide one spell-local helper for the common "this spell is no longer trustworthy; rebuild it on the next meld" path. This method is the spell-owned convenience wrapper over two different invalidation layers:
spell-local runtime invalidation
clear the cached CreationContext
force deferred runtime resolution to run again
lineage/control-plane invalidation
mark the lineage structurally gated in SpellSystemStates
Contract:
Safe to call multiple times on a live spell.
Requires the spell to be attached to a dynamic runtime environment.
Clears the spell-owned CreationContext so the cached runtime dispatch state cannot survive a structural invalidation.
Sets resolution_complete=False and resolution_required=True so the next meld re-enters the deferred runtime plan path after structural validation succeeds.
Uses SpellSystemStates.mark_structural_change(...) when the control-plane registry is available.
Defaults the reason to SpellStateChangeReason.structure_changed when callers do not supply a more specific reason.
Intentionally does not use transfer-only hard-disable semantics; this helper models the recoverable post-change posture rather than the unsafe mid-transfer posture.
- Parameters:
change_reason -- Optional structural change reason to record in the lineage state. When omitted, the helper uses SpellStateChangeReason.structure_changed.
- Returns:
None.
- Raises:
RuntimeError -- If the spell has already been cleaned, or if the spell is not attached to a dynamic runtime environment.
- property system_state: SpellSystemState | None๏
Return the SpellSystemState instance associated with this spell's lineage.
This is a read-mostly view into the change-control and validation state tracked by SpellSystemStates.
Contract:
Mutation and contract operations can ask for the current lineage state.
Higher-level dev-ops and validation pipelines can inspect this value while orchestrating Phase 1-7 revalidation.
Returns None when SpellSystemStates are unavailable or the lineage is not currently tracked.
- Returns:
The state object for this spell's lineage, if available.
- Return type:
Optional[SpellSystemState]
- property mutation_override: dict๏
Current persistent default override payload for this spell.
This payload is pre-normalized into the same override-map shape that meld-time runtime overrides use. It is conceptually separate from the caller-supplied spell_override argument passed into meld(...):
meld spell_override -> one-call runtime override payload
Spell.mutation_override -> persistent default override payload stored on the spell itself
Contract:
None is the ONLY inactive sentinel. An empty dict is never stored: apply_mutation_override({}) normalizes to None, so a caller testing == {} will never match. Test is None, or use has_mutation_override.
Positional payloads are normalized into {"__args__": [...]}.
EMPTY POSITIONAL IS NOT EMPTY. apply_mutation_override([]) stores {"__args__": []}, which is a non-empty dict and therefore reports has_mutation_override == True. Empty dict and empty list are deliberately NOT symmetric: {} clears, [] installs a positional override of zero arguments.
Keyword payloads are copied into a fresh dict so later meld calls do not depend on caller-owned containers.
Note
The declared return annotation is dict, but this property returns Optional[dict[str, Any]] - None is the normal inactive value. Trust the Returns block below over the signature.
- Returns:
The normalized persistent default override payload currently attached to this spell, or None when no default payload is active.
- Return type:
Optional[dict[str, Any]]
- property has_mutation_override: bool๏
Whether this spell currently has a non-empty mutation overlay.
This is a convenience for Dynamic or AI-native flows that want a quick check before doing more expensive revalidation or graph rebuilds.
Contract:
Truthiness test over the stored payload, so it is False exactly when the payload is None.
Reports True for a zero-argument POSITIONAL override, because [] normalizes to {"__args__": []} which is a non-empty dict. apply_mutation_override([]) therefore leaves this True while apply_mutation_override({}) leaves it False.
Unlike apply_mutation_override / clear_mutation_override, this does NOT require a dynamic environment and does not raise; it is safe to probe on any live spell.
- Threading:
Unsynchronized single-attribute read.
- Returns:
True when the current overlay payload is non-empty.
- Return type:
bool
- apply_mutation_override(override: dict | list | tuple | None) None[source]๏
Apply or replace the persistent default override payload for this spell.
Contract:
Requires the spell to be attached to a dynamic runtime environment.
Normalizes the payload into the same runtime override-map shape that meld-time caller overrides use.
Stores only the normalized runtime payload shape on the spell.
Does not invalidate the spell, clear CreationContext, or mark structural change state.
Treats None and empty dict payloads as "no active default override payload."
- Parameters:
override --
New persistent default override payload. Supported shapes match meld-time override payloads:
dict for targeted keyword-style overrides
list / tuple for root positional overrides
None to clear the default payload
- Returns:
None.
- Raises:
RuntimeError -- If the spell is not attached to a dynamic runtime environment.
TypeError -- If override is not one of the supported override payload shapes.
- clear_mutation_override() None[source]๏
Clear any active persistent default override payload for this spell.
Contract:
Requires the spell to be attached to a dynamic runtime environment.
Resets the stored payload back to None.
Does not invalidate the spell or rebuild runtime shape.
- Returns:
None.
- Raises:
RuntimeError -- If the spell is not attached to a dynamic runtime environment.