On this page
SpellSpace๏
Use md.SpellSpace from the public package namespace.
- class SpellSpace(*, owner_conduit_id: str, conduit_meld: ConduitMeld, owner_conduit_creations: ConduitCreations, spellspace_registry: set[SpellSpace], spellspace_pool: SpellSpacePool, spellspace_stack_state: SpellSpaceThreadState)[source]๏
Explicit scope handle for Existence.unique_per_spell_space.
- Purpose:
Represent one spellspace-bound resolution window without storing a live conduit back-reference. The conduit remains the factory for spellspaces, but the runtime scope object carries only the explicit collaborators it needs to execute, reset, and unregister itself.
Contract:
Owns one stable spellspace id and one stable owner conduit id.
Delegates runtime execution through one owned SpellSpaceMeld.
Clears spellspace-scoped instances through the injected Creations.
Unregisters itself from the injected spellspace registry on cleanup.
Does not own conduit-wide resolution caches or control-plane state.
Acts as its own context manager for the managed with conduit.enter_spellspace() as space: lane: enter_spellspace() acquires and activates the space (pool acquire plus thread-stack push) before the with statement runs, so __enter__ is a trivial self-return and __exit__ performs the LIFO pop-validated recycle. No per-cycle wrapper object exists.
Nested managed scopes are first-class: each enter_spellspace() call pushes one new independent scope onto the per-thread stack (A -> B -> C -> D to any depth), each scope owns its own spellspace-local storage, and exits must unwind in LIFO order.
One managed activation per acquisition: after __exit__ recycles the space back to the pool, re-entering the same object is a caller contract violation (the trusted-private-caller posture documented on SpellSpacePool.release); LIFO validation in pop_expected fails fast on the common misuse shapes.
Carries one lease flag, _released: the pool sets it on release and clears it on acquisition, and a released space refuses meld and purge with SpellSpaceScopeError. After permanent cleanup it stays True as a documented tombstone.
Every exit finishes its pool return (or destroy) when a disposal method fails - the store is emptied before any method runs - and then raises the disposal ExceptionGroup.
Threading:
Uses an internal RLock for cleanup/reset idempotence.
The managed enter/exit lane itself is thread-confined by construction (pool deque hand-off plus per-thread stack), matching the recycle_from_managed_context confinement contract.
Lifecycle:
Created by Conduit.create_spellspace(...) or Conduit.enter_spellspace(...).
Normal cleanup returns the spellspace to its conduit-local pool.
Permanent cleanup drops all injected collaborators.
- Registration:
MELDER KERNEL - guarded, access=public. Users DRIVE it as a context manager (with conduit.enter_spellspace() as space:) and meld against the active space, but never construct or bind() it - the conduit is the factory and the guard refuses binding.
- Subsystem Context:
The scope handle of the conduit spell_space subsystem, backing Existence.unique_per_spell_space. The conduit is the factory; this object carries only the explicit collaborators it needs (an owned SpellSpaceMeld for execution, an injected Creations for its scoped instances, and the registry/pool it unregisters and recycles into). It holds NO live conduit back-reference. Managed entry lives on a per-thread stack, so nested enter_spellspace() scopes (A -> B -> C) each own their storage and must unwind LIFO.
- System Context:
This is how the DGR gives a caller an EXPLICIT, nestable resolution window without leaking conduit-wide state into it: instances resolved as unique_per_spell_space live and die with the space - every exit clears them before the space goes back to its pool, and a released space refuses meld, so a recycled shell cannot serve an object built through a stale handle. Making the space its own context manager (trivial __enter__, LIFO-validated __exit__ recycle) and confining the managed lane to one thread is what lets the pool hand spaces back and forth without per-cycle wrapper objects or cross-thread synchronization.
AGENT_ACCESS: public
- AGENT_PURPOSE:
access: public. Explicit request scope for Existence.unique_per_spell_space. Enter via conduit.enter_spellspace(); the block exit clears spellspace-scoped instances and returns the space to its pool; a released space refuses meld and purge.
- cleanup() None[source]๏
Cleanup this spellspace through either the reusable or permanent lane.
Contract:
Normal cleanup returns this spellspace to the conduit-local pool after reusable cleanup. A space that is already released is left as it is, so a second cleanup never pools it twice.
permanent_cleanup() forces the destructive lane even when a pool is attached.
Either lane finishes when a disposal method fails (the store is emptied before any method runs), then the disposal ExceptionGroup propagates.
- Raises:
ExceptionGroup -- Disposal failures, after the space is pooled or destroyed.
- Returns:
None.
- permanent_cleanup() None[source]๏
Permanently destroy this spellspace instead of returning it to a pool.
Contract:
Flips the permanent cleanup flag immediately.
Reuses the normal cleanup entrypoint so all public teardown still flows through one surface.
- Returns:
None.
- recycle_from_managed_context() None[source]๏
Recycle one managed pooled spellspace through the fast common lane.
- Purpose:
Avoid the generic cleanup branch work on the common enter_spellspace() managed exit path, where the spellspace is untracked in the registry and is expected to return directly to the conduit-local pool after clearing only spellspace-local state.
Contract:
Valid only for live managed spellspaces acquired through the untracked pool path; a space that is already released (or destroyed) returns at once.
Falls back to the generic cleanup entrypoint when permanent teardown was requested or the spellspace is registry-tracked.
Clears spellspace-local creations before returning this spellspace to the pool.
Keeps collaborator references intact for later reuse, restoring temporary hooks after disposal and before idle publication.
Finishes the hook reset and pool release when a disposal method fails (the store was swapped empty first), then the disposal ExceptionGroup propagates.
Threading / Concurrency:
This lane runs without the spellspace RLock because managed spellspaces are thread-confined by construction: the pool's deque pop hands the object to exactly one thread, the object lives only on that thread's SpellSpaceThreadState stack, and pop_expected(...) validates LIFO ownership before this method runs. The pool's deque append on release is the hand-off point to the next acquiring thread.
The spellspace-local clear uses Creations.reset_for_pool_unlocked(): the same thread confinement that justifies skipping the spellspace lock also covers the store's internal lock on this lane. The clear remains explicit and immediate, not deferred; disposal-bearing stores still fall back to the fully locked teardown flow inside that method.
Concurrent external cleanup() / permanent_cleanup() against an in-flight managed spellspace is a caller contract violation (the object is not idle in the pool and not registry-tracked), matching the trusted-private-caller posture documented on SpellSpacePool.release(...).
- Raises:
ExceptionGroup -- Disposal failures, after the space is back in its pool.
- Returns:
None.
- property id: str๏
Return the stable identifier for this spellspace.
Contract:
The space's versioned identity, assigned at construction.
NOT check_cleaned() guarded, so it stays readable on a recycled or cleaned space - useful for logging a space you no longer hold.
- Threading:
Unsynchronized read; safe from any thread.
- Lifecycle / Cleanup:
Readable after cleanup, by design.
- Returns:
Unique id assigned at construction.
- Return type:
str
- property owner_conduit_id: str๏
Return the stable owner conduit id for this spellspace.
Contract:
The conduit this space belongs to, fixed at construction - a pooled space is never re-homed to a different conduit.
NOT check_cleaned() guarded, matching id.
- Threading:
Unsynchronized read; safe from any thread.
- Lifecycle / Cleanup:
Readable after cleanup, by design.
- Returns:
Owner conduit id injected at construction time.
- Return type:
str
- meld(spell: str | object | None = None, *, spell_id: str | None = None, spellframe: str | object | None = None, binding_name: str | None = None, override: dict | list | tuple | None = None) object[source]๏
Delegate one meld call through the injected Meld runtime.
- Call shape:
Positional strings are human SpellNames. Machine callers use keyword-only spell_id=.... A warm id meld is served here from the spellspace door's fast-door entry; any other id meld is forwarded positionally to the door's existing ID fast lane.
Contract:
Delegates resolution and lifecycle behavior to the shared conduit meld runtime through its spellspace front door.
Keeps human spell and machine spell_id identities mutually exclusive.
Warm id lane (2026-09-26): a spell_id=... meld with no spell, spellframe or binding_name reads the door's fast-door entry and applies the same guard ladder and arms as SpellSpaceMeld.meld (plain, non-empty dict override, bound existing object). A hit returns without entering the door; a miss or any failed guard continues in the door, so results, errors and the cache-emit check are identical to calling the door.
Warm name/class lane (2026-09-27): a meld("Name") or meld(spell=Cls) with no spellframe or binding_name reads the door's name/class registry with the same guards and arms; the door mints that entry after one successful meld of the shape, so a hit and the door agree. An unhashable spell, an instance or a callable as spell are misses and continue in the door.
Propagates runtime failures from the meld pipeline unchanged.
A space released to its pool raises SpellSpaceScopeError before any lookup; a permanently cleaned one raises RuntimeError.
- Returns:
The resolved runtime object returned by the shared meld runtime.
- Return type:
- Parameters:
spell -- Human SpellName string or concrete spell/frame object.
spell_id -- Optional canonical SHA256 machine identity.
override -- Optional positional or keyword override payload.
- purge(spell: str | object | None = None, *, spell_id: str | None = None, spellframe: str | object | None = None, binding_name: str | None = None, purge_all: bool = True) int[source]๏
Purge a registered target's retained creations from this SpellSpace.
- Purpose:
Expose request-local retirement through the owned SpellSpaceMeld door while keeping this explicit scope usable.
Contract:
SpellSpaceMeld authorizes only many and unique_per_spell_space.
The target store is always this space's own Creations. No conduit, Spell owner, lineage-root or cluster team store can be selected.
Identity normalization follows meld's name/type/frame/id rules.
Purge does not exit the scope, pop its stack or return it to a pool.
- Parameters:
spell -- Logical name, class/function reference or application instance. An instance is inspected for its class before ordinary lookup. The original reference is retained for single-object removal.
spell_id -- A version's spell_id, mutually exclusive with spell. It names exactly that version - active or parked, the owner conduit's Book's own or a borrowed copy - and this space's entries of it.
spellframe -- Optional frame/type used by ordinary binding discovery.
binding_name -- Optional binding name within that frame.
purge_all -- True removes every retained local entry for the target. False requires an instance as spell and removes only that object.
- Returns:
Removed local creation count; zero when none are retained.
- Return type:
int
- Raises:
ValueError -- If selectors conflict, no target is supplied, or single-object removal is requested without an instance.
KeyError -- If no version this space's Book can see carries the spell_id, or normal meld discovery cannot find the binding.
RuntimeError -- If permanently cleaned or the target has a broader lifetime.
SpellSpaceScopeError -- If this space was released to its pool.
TypeError -- If purge_all is not a bool.
ExceptionGroup -- Disposal failures after selected local entries have been removed.
- Threading / Lifecycle:
Creations uses this space's store lock and releases it before disposal. Direct manual use needs no active managed stack entry. Managed thread confinement and pool ownership rules remain unchanged; a returned/recycled space refuses purge until it is acquired again.