On this page

Spell๏ƒ

Use md.Spell from the public package namespace.

Implementation source

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:

  1. spell-local runtime invalidation

    • clear the cached CreationContext

    • force deferred runtime resolution to run again

  2. 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.

Topic reference ยท Full contents