On this page
- Conduit
ConduitConduit.cleanup()Conduit.permanent_cleanup()Conduit.get_active_spellspace()Conduit.create_spellspace()Conduit.enter_spellspace()Conduit.prewarm_spellspaces()Conduit.prewarm_lesser_conduits()Conduit.idConduit.nameConduit.spellbookConduit.get_conduit_cloud()Conduit.hooks_modifiedConduit.register_conduit_hooks()Conduit.set_conduit_hooks()Conduit.upgrade_to_normal()Conduit.policyConduit.set_new_policy()Conduit.create_lesser_conduit()Conduit.enter_lesser_conduit()Conduit.get_conduit_by_spell_id()Conduit.check_spell_id()Conduit.get_spell_by_spell_id()Conduit.get_spell_by_index_id()Conduit.find_contracted_spell()Conduit.find_spell_id()Conduit.find_spell_key()Conduit.inspect_spell()Conduit.begin_transaction()Conduit.end_transaction()Conduit.transaction()Conduit.add_bind_hooks()Conduit.clear_bind_hooks()Conduit.bind()Conduit.bind_inactive()Conduit.scan()Conduit.get_spell_permissions()Conduit.mutation_researchConduit.transfer_spell_ownership()Conduit.enable_meld()Conduit.disable_meld()Conduit.meld()Conduit.managed_spell_meld()Conduit.purge()Conduit.meld_existing_spell()Conduit.has_live_creation()Conduit.describe_live_creation_status()Conduit.describe_spells_in_conduit()Conduit.link()Conduit.notch_spell()Conduit.add_to_spell_index()Conduit.remove_from_spell_index()Conduit.cleanup_spell()Conduit.sever_link()Conduit.get_links()Conduit.get_lesser_conduit()Conduit.get_initiated_conduit()Conduit.get_provider_conduit()Conduit.get_initiated_conduits()Conduit.get_provider_conduits()Conduit.cleanup_lesser_conduits()Conduit.get_resolution_state()Conduit.validate_resolution()Conduit.add_spell_to_contract()Conduit.add_index_to_contract()Conduit.remove_index_from_contract()Conduit.add_spells_to_contract()Conduit.remove_spell_from_contract()Conduit.remove_spells_from_contract()Conduit.remove_root_from_contracts()Conduit.add_spell_to_contract_with_dependencies()Conduit.get_all_spells_in_contracts()Conduit.get_spell_in_contracts()Conduit.get_spells_in_contract_by_conduit()Conduit.get_spells_in_contract_by_conduit_name()Conduit.get_contracted_conduits()Conduit.snapshot_state()Conduit.validate_contracts_and_define()Conduit.validate_received_contracts()
Conduitο
Use md.Conduit from the public package namespace.
- class Conduit(spellbook: Spellbook, configuration: SpellbookConfiguration, conduit_state: ConduitState, aetheric_frame_name: str, aetheric_frame: AethericFrame, policy: Policies, creation_gate_controller: CreationGateController, dynamic: bool = False, name: str | None = None, logger: Any | None = None, conduit_id: str | None = None, root_conduit_id: str | None = None, creation_gate: CreationGate | None = None, conduit_hooks: dict[str, list[Any]] | None = None, meld_hooks: dict[str, list[Callable[[...], Any]]] | None = None)[source]ο
A Conduit is the runtime scope, execution boundary, and contract-aware access surface for one branch of the Melder graph.
At runtime a conduit acts as the object that owns meld execution, spellspace scope, contract/link behavior, lesser-conduit lineage, and access to the frame-level services needed to create, share, and tear down spell-backed objects safely.
Contract:
Owns one meld runtime, one creations manager, one conduit ward, one creation gate, spellspace tracking state, and conduit-local hook overlays.
Can create lesser conduits beneath its current root lineage.
Can link to peer conduits only when the runtime is in dynamic mode and the active policy allows it.
Uses a CreationGate to control meld entry and track in-flight meld work for safe drain and shutdown behavior.
Normal conduits own the Spellbook lifecycle; lesser conduits share the parent Spellbook and retire only their own named discovery entry, never root ownership.
Becomes unusable after cleanup completes.
- Meld gating:
Each conduit owns a CreationGate that can block or deny new meld calls. The gate tracks active melds via ticket registration so the system can drain in-flight work before shutdown or dynamic reconfiguration.
Threading / Concurrency:
Uses an internal RLock for multi-step conduit state transitions.
Relies on CreationGate and CreationGateController for meld admission and lineage-aware gate control.
Delegates current-frame registration to the injected AethericFrame and reads lookup/cluster coordination through the frame-owned cloud service.
Delegates gate governance to the injected frame-owned CreationGateController.
Lifecycle / Cleanup:
Normal and lesser conduits follow different cleanup paths.
Cleanup tears down meld/runtime state first, then contracts/links, then owned registries and logger state.
Logger cleanup is intentionally last.
- Registration:
MELDER KERNEL - guarded. A conduit is obtained from Spellbook.conjure(...) or Conduit.create_lesser_conduit(...), never constructed directly and never bound as a spell. Guarding does not restrict USE: the conduit is the primary object a user holds and calls meld(...) on.
- Subsystem Context:
The owner of the whole conduit subsystem. It composes one ConduitMeld (resolution), one ConduitCreations (live-object storage), one ConduitWard (contracts, policies, lineage), one CreationGate (admission), one SpellSpacePool, and one ConduitPool. Everything else in this package is reached THROUGH a conduit - which is why the vocabulary classes (Policies, Permissions, ConduitState) are the values a user hands to conduit verbs.
- System Context:
A conduit is the boundary at which Melder's promises become concrete. Layer 4 of the runtime (Aether -> AethericFrame -> Spellbook -> CONDUIT -> Meld -> Creations): a Spellbook conjures exactly ONE conduit, and from that point the conduit is what the user actually holds. Two invariants explain most of its surface. First, DYNAMIC MODE GATES STRUCTURE: linking, severing, ownership transfer, and lesser-to-normal upgrade all require dynamic mode, because each rewires the resolution graph after conjure and an automatic-mode world promises a fixed, self-contained graph. Second, DRAIN BEFORE MUTATE: the CreationGate exists so in-flight melds can finish before shutdown or reconfiguration rather than being torn out mid-resolution - which is why the gate tracks tickets rather than just holding a boolean. The normal/lesser split is a lifetime story, not a capability one. A lesser conduit shares its parent's Spellbook and does not unregister frame-level state, so tearing one down cannot damage the root; upgrading one to normal PRESERVES its already-constructed objects rather than rebuilding them, because callers may already hold those instances.
AGENT_ACCESS: public
- AGENT_PURPOSE:
access: public. The runtime scope you hold after conjure. Call meld(...) to resolve instances, create_lesser_conduit(...) for child scopes, enter_spellspace() for request scope, and link(...)/sever_link(...)/transfer_spell_ownership(...) in dynamic mode only.
- cleanup() None[source]ο
Public API
Release this scope, recycling a lesser or permanently tearing down a root.
Contract:
Permanent cleanup is idempotent after _cleaned flips. A successful soft lesser return ends its current use; callers must reacquire it through create_lesser_conduit before starting another use.
Soft cleanup of a lesser already in its pool (pooled_lesser) does nothing, so a second cleanup never pools the shell twice.
Permanent teardown fires on_conduit_cleanup_start and on_conduit_cleanup_complete. Soft return preserves the shell.
Dispatches to the lesser- or normal-conduit cleanup path based on the current conduit state.
Tears down logger state last, after the rest of the runtime surface has been released.
This is local conduit teardown only; it does not clean Aether or the owning frame itself.
Soft cleanup does not publish idle until descendants and named record/ directory retirement finish. A descendant that cannot finish its own return, or a failed retirement, keeps this scope owned for retry; already completed disposal work is not rolled back.
A failing disposal method stops neither path: the lesser still returns to its pool and a permanent teardown still finishes, and then every disposal failure is raised as one ExceptionGroup (since 0.2.8203; permanent teardown used to only log them).
- Returns:
None.
- Raises:
ExceptionGroup -- A disposal method failed (raised after the pool return or the teardown finished), or a descendant could not finish its own pool return (this scope stays attached for retry).
Exception -- Named record/directory retirement failed before pool return.
- 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.
- get_active_spellspace() SpellSpace | None[source]ο
Return the currently active SpellSpace for this Conduit, if any.
Contract:
THREAD-LOCAL: it returns the spellspace active on THE CALLING THREAD, not a conduit-wide value. Two threads inside the same conduit can see different answers, and one can see None while the other does not.
None means no spellspace is entered on this thread - a normal state, not an error.
- Threading:
Unsynchronized read; a snapshot only.
- Lifecycle / Cleanup:
Guarded by check_cleaned().
- Raises:
RuntimeError -- If the object has been cleaned.
- Returns:
The top-of-stack SpellSpace, or None if no spellspace is active.
- Return type:
SpellSpace | None
- create_spellspace() SpellSpace[source]ο
Create a SpellSpace bound to this Conduit.
- Purpose:
Create a new spellspace scope owned by this Conduit and register it for cleanup bookkeeping.
Contract:
Returns a new SpellSpace owned by this Conduit.
The SpellSpace is registered in the spellspace registry.
Lifecycle is manual unless used via enter_spellspace.
- Returns:
A new SpellSpace owned by this Conduit.
- Return type:
- enter_spellspace() SpellSpace[source]ο
Acquire and activate one managed spellspace scope.
- Usage:
with conduit.enter_spellspace() as space:
space.meld(...)
Contract:
Acquires one pooled spellspace and pushes it onto the calling thread's active-scope stack immediately (activation happens here, not in __enter__), then returns the space itself, which acts as its own context manager. No per-cycle wrapper object is allocated.
Nested activation is first-class: calling this inside an active scope pushes a new independent scope (A -> B -> C -> D to any depth); exits must unwind in LIFO order and are validated.
The space is cleaned (recycled to the conduit-local pool) on with-block exit, even on exceptions.
Callers that do not use a with block own the exit: they must call space.__exit__(None, None, None) (or unwind through conduit cleanup, which drains abandoned scopes best-effort).
- Returns:
The newly activated spellspace, already the current top-of-stack scope for the calling thread.
- Return type:
- Raises:
SpellSpaceScopeError -- On scope exit, if stack integrity is violated.
- prewarm_spellspaces(count: int) int[source]ο
Public API
Ensure pooled spellspace shells exist before traffic arrives.
- Purpose:
Move first-use spellspace construction cost (the shell, its spellspace-local creations registry, and its meld front door) from the first scope cycles to an explicit, owner-chosen moment.
Contract:
Acquires and immediately releases pooled spellspaces so the idle pool holds at least min(count, pool.max_idle) shells.
Clamped to pool capacity: never builds shells the pool would immediately evict and destroy.
Shells above the pool's baseline_idle stay idle like any burst the pool has seen (the builds count as misses) and decay back toward baseline_idle once no miss has happened for the pool's settle time (0.2.8234; through 0.2.8233 at most 20 were kept).
Prewarmed shells carry no scope contents and are not pushed on any thread's active-scope stack.
Idempotent in effect: already-idle shells count toward the target and are reused, not rebuilt.
Restore temporary owner hooks before publishing idle shells, just as normal Space return does. Acquisition reapplies current local owner hooks when the shell is actually leased.
- Parameters:
count -- Requested number of idle pooled spellspace shells. Must be positive.
- Returns:
Number of idle shells ensured (the capacity-clamped target).
- Return type:
int
- Raises:
ValueError -- If count is not positive.
RuntimeError -- If the conduit has been cleaned.
- prewarm_lesser_conduits(count: int) int[source]ο
Public API
Ensure pooled lesser-conduit shells exist before traffic arrives.
- Purpose:
Move first-use lesser construction cost (conduit shell, ward, creations registry, meld door, spellspace pool) from the first scope cycles to an explicit, owner-chosen moment. Useful for burst-concurrency starts; irrelevant for steady single-threaded reuse where one shell cycles forever.
Contract:
Creates and immediately soft-cleans lesser conduits through the normal create_lesser_conduit() / cleanup() lanes, so all lifecycle hooks configured for lesser creation fire per shell exactly as they would for real traffic.
Clamped to pool capacity: ensures at most min(count, pool.max_idle) idle shells.
Shells above the pool's baseline_idle stay idle like any burst the pool has seen (the builds count as misses) and decay back toward baseline_idle once no miss has happened for the pool's settle time (0.2.8234; through 0.2.8233 at most 20 were kept).
Idempotent in effect: already-idle shells are drained and returned, not duplicated.
- Parameters:
count -- Requested number of idle pooled lesser shells. Must be positive.
- Returns:
Number of idle shells ensured (the capacity-clamped target).
- Return type:
int
- Raises:
ValueError -- If count is not positive.
RuntimeError -- If the conduit has been cleaned or lesser creation is invalid for this conduit's lineage.
- property id: strο
Public API
Return the unique identifier of this conduit.
Contract:
The conduit's stable identity, assigned at construction and unchanged for its life - including across cluster join and leave.
- Threading:
Unsynchronized read; a snapshot only.
- Lifecycle / Cleanup:
Guarded by check_cleaned().
- Raises:
RuntimeError -- If the object has been cleaned.
- Returns:
This conduit's unique identifier.
- Return type:
str
- property name: str | Noneο
Public API
Return the human-readable name for this conduit, if one exists.
Contract:
NORMALIZES EMPTY TO NONE: an unnamed conduit and one named with an empty string are indistinguishable through this property, both reporting None.
Names are a convenience label, not identity - use id for identity.
- Threading:
Unsynchronized read; a snapshot only.
- Lifecycle / Cleanup:
Guarded by check_cleaned().
- Raises:
RuntimeError -- If the object has been cleaned.
- Returns:
The configured conduit name, or None when the conduit is unnamed.
- Return type:
Optional[str]
- property spellbook: Spellbookο
Public API
Return the Spellbook this conduit resolves through.
Contract:
A root conduit returns the Spellbook that conjured it, whose conduit property returns this root. A lesser returns the Spellbook it was built with, its root's. upgrade_to_normal rebinds the upgraded conduit to its new Spellbook, which this then returns.
BORROWED: reading it keeps nothing alive, and the caller cleans the Spellbook only if it owns it.
The mirror of Spellbook.conduit.
- Threading:
Unsynchronized read; a snapshot only.
- Lifecycle / Cleanup:
Guarded by check_cleaned().
- Raises:
RuntimeError -- If the conduit has been cleaned.
- Returns:
The borrowed Spellbook.
- Return type:
- get_conduit_cloud() ConduitCloud[source]ο
Public API
Return the frame-owned conduit cloud tied to this conduit.
Contract:
Reaches THROUGH the aetheric frame to the frame-owned cloud, so the returned object is shared by every conduit on the frame - it is BORROWED, never owned here, and must not be cleaned by the caller.
- Returns:
- The ConduitCloud managed by this conduitβs
AethericFrame.
- Return type:
ConduitCloud
- Raises:
RuntimeError -- If the conduit is cleaned.
- property hooks_modified: boolο
Report local lifecycle overlays or temporary Meld hooks on this conduit.
- Contract:
Diagnostic read under existing mutation locks. Root-shared changes update the baseline and do not themselves count as local divergence. Pool paths inspect existing local state and the Meld bool directly.
- Returns:
Whether lease return has local hook state to restore.
- Return type:
bool
- Raises:
RuntimeError -- This conduit or its Meld has been cleaned.
- register_conduit_hooks(hooks: dict[str, Any], *, create_local_hooks: bool = True, overwrite: bool = False) None[source]ο
Public API
Register hook callables for this Conduit.
The default is local additive registration. Explicit shared mode updates a normal root's live baseline so inheriting scopes see the changes without a hierarchy walk. Configuration and other normal roots are unaffected.
Contract:
Empty additive input is a no-op. Empty replacement selects both families.
SPLITS the supplied mapping into conduit-lane and meld-lane updates and applies each to its own registry, so one call can touch two subsystems.
Additive registration - it does not clear hooks registered earlier. overwrite=True replaces the supplied families instead.
Validates the whole batch before changing either family. Local lifecycle lists retain their existing event-shadow/fallback rules; local Meld updates copy the effective map. Shared mode selects the root baseline for the caller, dropping its selected local overrides.
Writers use existing locks and replace event lists. Readers retain current per-event semantics, not a whole-operation callback snapshot.
- Parameters:
hooks -- Mapping of hook name -> callable or iterable of callables.
create_local_hooks -- True isolates changes on this conduit. False is normal-root-only and publishes into its stable lineage maps.
overwrite -- True replaces each supplied family; omitted families stay unchanged. An empty replacement clears local lifecycle overlays (revealing inherited hooks) and installs an empty local Meld map; shared empty replacement clears both root baselines.
- Raises:
RuntimeError -- Cleaned conduit or a shared update attempted through a lesser.
ValueError / TypeError -- If hook names or values are invalid.
- Returns:
None.
- set_conduit_hooks(hooks: dict[str, Any], *, create_local_hooks: bool = True, overwrite: bool = True) None[source]ο
Replace supplied runtime hook families, with local state as the default.
- Parameters:
hooks -- Lifecycle/Meld events and callable or list/tuple values. Empty input replaces both families; it clears local lifecycle overlays and mutes local Meld callbacks, or clears shared roots.
create_local_hooks -- True changes this scope only. False publishes a normal root baseline update to inheriting scopes.
overwrite -- True replaces the selected family maps. False explicitly selects additive registration through the same implementation.
- Contract:
Delegates complete validation, root authority and mutation locking to register_conduit_hooks. Callback objects are not cloned or invoked.
- Returns:
None.
- Raises:
RuntimeError -- Cleaned scope or shared changes requested from a lesser.
ValueError -- Unknown hook event.
TypeError -- Invalid callback payload.
- upgrade_to_normal(name: str, *, configuration: SpellbookConfiguration | None = None, hooks: dict[str, Any] | None = None) None[source]ο
Public API
Promote this childless lesser into an independent normal root in place.
- Purpose:
Keep this runtime's identity and retained creations while giving it a fresh, empty Spellbook for its own bindings and links. Spellbook's private existing-conduit conjure route owns configuration, phases, attachment and normal activation; this method prepares its target.
Contract:
Requires a live, attached, childless lesser in a dynamic frame.
The new root has no parent or inherited definitions/contracts. Old spell IDs are no longer resolvable; retained objects remain in their existing stores for eventual disposal.
A retained object may hold references to instances the former lineage owns (a unique instance of a former root's spell, a lineage instance): those are disposed by their own owner, on that owner's schedule, not with this conduit, so a retained holder can outlive what it references. Melder does not serve a retained holder again (its spell ID no longer resolves) and never revokes references application code keeps.
Uses ordinary Spellbook configuration selection: omitted local configuration means fresh defaults; frame-wide sharing adopts its canonical configuration and refuses a conflicting supplied object.
Bind callbacks start empty unless the selected configuration seeds them. Conduit/Meld hooks likewise start from that configuration. Changes to the new Book's Bind registry never change the old Book.
Validates hooks before mutation. Configuration/setup failures before Book attachment restore the lesser and retire only newly owned state. After attachment, publication failures leave a normal root whose cleanup belongs to the caller, as with ordinary conjure.
Reserves the requested name during preparation, retaining any existing lesser entry until root registration atomically replaces its alias. Same-name promotion is legal. Failure releases the temporary claim.
- Parameters:
name -- Name for the new root and ConduitCloud registration.
configuration -- Prepared same-frame configuration, or None for ordinary default/shared selection. A local configuration already owned by the former Book cannot be reused; supply a new one instead.
hooks -- Optional local runtime additions, installed after normal conjure activation. Values are callables or lists/tuples of callables.
- Raises:
RuntimeError -- Invalid lifecycle/posture, children, detached target, configuration conflict, gate drain timeout or conjure failure.
ValueError -- Duplicate name, invalid configuration, or unknown hook.
TypeError -- Invalid name, configuration type or hook payload.
- Returns:
None. The same Conduit becomes the new Book's sole normal root.
- Threading / Lifecycle:
Drains this conduit before taking structural locks. Parent ward is locked before the target conduit/ward for detachment. Admission is restored before activation callbacks; an initially parked gate stays parked. Callers must quiesce concurrent scope acquisition, managed SpellSpaces on other threads, and lineage mutation/teardown during graduation. No locking or checks are added to ordinary meld calls.
- property policy: Policiesο
Public API
Return the linking policy currently in force on this Conduit's ward.
- Purpose:
The counterpart read for set_new_policy. Without it the policy is a WRITE-ONLY setting: a caller could change how linking behaves and then had no public way to ask what the behaviour now is. Melder does not conflate "I set it" with "it is in force" anywhere else, and the ward is no exception - set_new_policy can refuse (lesser conduit, existing contracts, automatic frame), so the value a caller last passed is not evidence of the value that is live.
Contract:
Reports the LIVE ward policy, not a remembered argument. After a set_new_policy that raised, this still reads the policy that survived the refusal.
Available in every mode. Unlike set_new_policy, reading is not gated on a dynamic frame - an automatic conduit can be asked what it enforces even though it can never be told to enforce something else.
Available on lesser conduits, which also cannot be written to.
Returns the Policies MEMBER, not its name. Use .name for the string form; .value is an integer because Policies is built on auto().
The returned member may be passed straight back into set_new_policy, which accepts a member or its string name.
- Threading:
Unsynchronized read of a single attribute. A caller racing set_new_policy observes either the old or the new member and never a partial state, but the answer is a snapshot - do not cache it across an operation that may re-policy the conduit.
- Lifecycle / Cleanup:
Guarded by check_cleaned(). The ward is owned by this conduit and is torn down with it.
- Returns:
The linking policy the ward is currently enforcing.
- Return type:
- Raises:
RuntimeError -- If the Conduit has been cleaned.
- set_new_policy(policy: str | Policies) None[source]ο
Public API
Sets a new policy for this Conduit. This is only allowed in dynamic mode.
Contract:
DYNAMIC MODE ONLY. On an automatic frame this raises RuntimeError rather than silently ignoring the request, and the refusal is logged.
Applies the policy through the conduit ward under the conduit lock, so the swap is atomic with respect to other conduit operations.
NOT A CONFIRMATION. A successful return means the ward accepted the swap; read policy when you need the value that is live.
- Parameters:
policy (Union[str, Policies]) -- The new policy to set, governing linking behavior. Accepts a Policies member or its lowercase string name, so the member returned by policy round-trips back through this call unchanged.
- Raises:
RuntimeError -- If dynamic environment is not enabled.
ValueError -- If policy is a string that names no Policies member.
- Returns:
None.
- create_lesser_conduit(logger: Any | None = None, *, name: str | None = None) Conduit[source]ο
Public API
Creates a lesser Conduit (child node) attached to this Conduit.
The lesser conduit inherits the parent's Spellbook, Configuration, and injected frame-owned services, but is restricted in its ability to establish external links or register new spells. It owns a conduit-local CreationGate created by the lineage CreationGateController. Named acquisition publishes current Nexus metadata on both fresh and pooled paths before post-created callbacks. Anonymous fresh allocation keeps its existing publication; anonymous pooled cycles remain local without refreshing Nexus or dev-ops identity metadata.
If this (parent) Conduit has lifecycle hooks attached via the Configuration for its Spellbook, the following hooks will be fired in order:
- "on_conduit_pre_created"
Fired before the lesser Conduit is constructed.
Signature:
hook(parent_conduit)
- "on_conduit_activated"
Fired immediately after the lesser Conduit instance has been constructed (its __init__ has run).
Signature:
hook(new_conduit)
- "on_conduit_post_created"
Fired after the lesser Conduit has been constructed and linked into this parent's ConduitWard.
Signature:
hook(parent_conduit, new_conduit)
- Concurrency:
The parent lock is held only for the cleaned re-check and the ward link plus named-only publication (a narrow window inside _link_new_lesser_under_lock). Pool acquisition, fresh construction, pooled-shell reactivation, hook firing, and anonymous Nexus publishing run outside the parent lock, so concurrent lesser creation from many threads does not serialize on this parent. Hook implementations must be thread-safe under concurrent lesser creation.
Contract:
The ROOT is resolved before anything is built: a normal conduit is its own root; a lesser borrows the original root's Book and pool while preserving this caller as its immediate parent.
Lesser conduits are a LINEAGE attachment, not a peer link; this is why link() explicitly refuses a lesser target.
A supplied name is an exact, nonempty, frame-wide unique string in either mode. Fresh and pooled scopes receive it before activation; Cloud publishes it with parent attachment, before post-created.
Names are creation-only. Cleanup unregisters and clears a name before pool return; unnamed scopes perform no directory mutation.
Discovery returns a borrowed reference and does not extend lifetime.
- Returns:
The newly created lesser Conduit instance.
- Return type:
- Raises:
RuntimeError -- If the parent or named child is cleaned during acquisition.
ValueError -- Name is empty or already owned/reserved in this frame.
TypeError -- A supplied name is not a string.
- Parameters:
logger -- Optional logger; its existing positional calling convention is retained.
name -- Optional exact name for this use of the child scope.
- enter_lesser_conduit(logger: Any | None = None, *, name: str | None = None) Conduit[source]ο
Public API
Create a lesser conduit for use as a with block scope.
- Usage:
with conduit.enter_lesser_conduit() as lesser:
service = lesser.meld(spell_id=service_id)
# the block exit ran lesser.cleanup(): its objects are disposed and # the shell is back in the root's pool
Contract:
Returns exactly what create_lesser_conduit(logger, name=name) returns: a live lesser attached to this conduit, named when name is given.
with calls cleanup() at block exit, even when the block raised: the lesser disposes its descendants, SpellSpaces and own creations and returns to its pool. Disposal failures are raised after the return as one ExceptionGroup, carrying the block's exception as __context__ when the block raised too.
Plain: nothing is pushed on a per-thread stack and no implicit current scope is tracked, so the call costs what create_lesser_conduit costs and blocks nest freely.
Called without with, the caller calls cleanup() itself, exactly as for create_lesser_conduit.
- Parameters:
logger -- Optional logger, passed to create_lesser_conduit unchanged.
name -- Optional exact name for this use of the child scope.
- Returns:
The new lesser conduit, to use as the with target.
- Return type:
- Raises:
RuntimeError -- If this conduit or the named child is cleaned during acquisition.
ValueError -- Name is empty or already owned/reserved in this frame.
TypeError -- A supplied name is not a string.
- get_conduit_by_spell_id(spell_id: str, aetheric_frame_name: str = 'default') Conduit[source]ο
Public API
Retrieves the conduit that has registered a spell with the given spell_id.
This method queries the Aether to find the original source conduit for a specific spell ID.
Contract:
Searches ONE frame: this conduit's Spellbook frame by default ("default" means that frame), or the frame you name. An id bound only in another frame is not found unless you name that frame.
A miss RAISES; it never returns None. The get_* lookups raise ValueError on a miss and the find_* lookups return None (owner decision 2026-10-11; the convention of the Aether conduit and frame lookups). Until 0.2.8230 this docstring and the annotation promised None, which the method never returned.
Runs under the conduit lock.
- Parameters:
spell_id (str) -- The unique identifier of the spell.
aetheric_frame_name (str) -- The aetheric frame to check against. Defaults to "default".
- Returns:
The root conduit that owns the spell.
- Return type:
- Raises:
RuntimeError -- If the Conduit is cleaned.
ValueError -- If no conduit in the frame claims the id - unknown or removed, bound in another frame, its owner cleaned, or its SpellIndex between owners while an ownership transfer runs - or the frame does not exist.
- check_spell_id(spell_id: str, aetheric_frame_name: str = 'default') bool[source]ο
Public API
Checks if a spell with the given spell_id exists within the global Aether registry.
Contract:
An EXISTENCE PROBE across the Aether rather than a local check, so a True answer does not mean this conduit can reach or meld the spell - only that the id is known.
Runs under the conduit lock.
- Parameters:
spell_id (str) -- The unique identifier of the spell to check (version SHA).
aetheric_frame_name (str) -- The Aetheric Frame to search within. Defaults to "default".
- Returns:
True if the spell exists in the Aether, False otherwise.
- Return type:
bool
- Raises:
RuntimeError -- If the Conduit is cleaned.
- get_spell_by_spell_id(spell_id: str, aetheric_frame_name: str = 'default') Spell | None[source]ο
Public API
Return the spell that owns spell_id - the spell_id bind or bind_inactive returned - from the Spellbook of the conduit that owns it.
The method:
Uses Aether to locate the conduit that owns the spell_id.
Looks the spell_id up in that conduit's Spellbook (Spellbook.find_spell_by_spell_id): the spell bound under it, active or parked.
Returns that Spell instance.
Contract:
A lookup by spell_id returns the spell that owns the spell_id, never the spell its SpellIndex has active in its place; that is a lookup by the index's id (get_spell_by_index_id). A spell_id and a SpellIndex are separate things (owner ruling, 2026-10-17). Until 0.2.8253 this method was get_spell_by_id, and a parked spell_id answered with the spell its index had active.
Resolves via the spellbook's Aether-wide lookup, so the returned spell may belong to a different conduit; ownership and permission are separate questions from resolvability.
Unlike its siblings, this one does NOT hold the conduit lock across the lookup.
- Parameters:
spell_id (str) -- The spell_id of the spell (SHA256), active or parked.
aetheric_frame_name (str) -- The aetheric frame to check against. Defaults to "default".
- Returns:
The spell that owns spell_id, or None when the owner's Spellbook holds no spell under it (it moved or left between the frame lookup and the Book's).
- Return type:
Optional[Spell]
- Raises:
RuntimeError -- If the Conduit is cleaned, or the owning conduit has no spellbook.
ValueError -- If no conduit in the frame claims the id - unknown or removed, bound in another frame, its owner cleaned, or its SpellIndex between owners while an ownership transfer runs - or the frame does not exist. A miss raises, as the get_* lookups do (owner decision 2026-10-11); until 0.2.8230 this docstring promised None.
- get_spell_by_index_id(spell_index_id: str) Spell | None[source]ο
Public API
Retrieve a spell object by the stable id of its SpellIndex.
- Purpose:
Expose the Spellbook-owned SpellIndex lookup path on the conduit facade so higher runtime surfaces can consume spell_index_id directly.
Contract:
Resolves by SPELL INDEX id, so it addresses a whole SpellIndex rather than one version - the spell you get back is the index's current selection, not a fixed version.
Logs and handles an unavailable spellbook rather than dereferencing it, so a torn-down conduit fails loudly rather than with an AttributeError.
- Parameters:
spell_index_id -- Stable SpellIndex id (ULID) to resolve.
- Returns:
Matching spell object when found, otherwise None.
- Return type:
Optional[Spell]
- Raises:
RuntimeError -- If the Conduit has been cleaned or the Spellbook is unavailable.
- find_contracted_spell(spell_id: str) Spell | None[source]ο
Internal
Locate a contracted spell by its version spell_id across all peer conduits in this Spellbook.
- Parameters:
spell_id (str) -- The unique version ID (SHA) of the spell to find.
Contract:
Searches CONTRACTED spells across EVERY peer conduit's contract map in this spellbook, not just this conduit's own - it answers "is this spell reachable to me by contract", not "did I bind it".
Returns None when no contract exposes the id; that is a normal answer, not an error.
- Threading:
Lock-free, like the other Conduit lookups. A link or sever started by a peer adds or removes that peer's id in the Book's _contracted_spells under the Book lock, holding the peer's conduit lock, not this one, so the peer ids are taken with one list(...) call - exact under concurrent writers on 3.14t, where walking the live keys raised "dictionary changed size during iteration" - and each peer is answered by Spellbook._find_contracted_spell_by_id, lock-free and keyed first. The copy is O(peers), the order of the walk itself. The Book lock is not taken: conjure holds it while phase workers and hooks run, and a hook calling this would deadlock. The conduit lock this used to take excluded none of those writers and made the parked-copy branch take a spell lock under it. A peer linked or severed during the call may be missed or still answered. (lock_residuals, 0.2.8232)
- Lifecycle / Cleanup:
Guarded by check_cleaned(). A teardown of this conduit racing the call is unsupported, as for every Conduit lookup.
- Raises:
RuntimeError -- If the conduit has been cleaned.
- Returns:
The contracted spell instance, or None if not found.
- Return type:
Optional[Spell]
- find_spell_id(spellframe: str, spell_name: str, binding_name: str) str | None[source]ο
Public API
Finds a spell's current version ID (SHA256 spell_id) using its logical identifiers.
This now uses:
Spellbook.find_spell_index(...) to locate the SpellIndex.
Spellbook._find_spell(SpellIndex) to retrieve the Spell.
Returns spell.spell_id (the version that SpellIndex selects now).
Contract:
TRANSLATES THE UNDERLYING ERROR: the spellbook raises RuntimeError for a missing key and this method re-raises it as ValueError, chaining the original. Catch ValueError here, not RuntimeError.
The translation is deliberate - at the conduit boundary a missing spell is a caller-input problem, not a runtime fault.
- Parameters:
spellframe (str) -- The logical namespace or grouping label.
spell_name (str) -- The name of the spell class or function.
binding_name (str) -- The secondary key to distinguish the spell.
- Returns:
The current SHA256 identifier of the spell.
- Return type:
Optional[str]
- Raises:
ValueError -- If the spell is not found in the spellbook.
- find_spell_key(spellframe: str, spell_name: str, binding_name: str) tuple | None[source]ο
Public API
Finds a spell's primary lookup key using its logical identifiers.
The key is typically a tuple used for internal retrieval within the spellbook.
Contract:
Treats a FALSY key as not-found and raises ValueError, so this never returns an empty key.
Like find_spell_id, it presents a missing spell as a caller-input error at the conduit boundary.
- Parameters:
spellframe (str) -- The logical namespace or grouping label.
spell_name (str) -- The name of the spell class or function.
binding_name (str) -- The secondary key to distinguish the spell.
- Returns:
The spell's key (frame, name, binding_name) tuple.
- Return type:
Optional[tuple]
- Raises:
ValueError -- If the spell is not found in the spellbook.
- inspect_spell(spell: Any, aetheric_frame: str = 'default') str | None[source]ο
Public API
Inspects any object to determine if it is a valid, registered spell in the Aether Registry.
This method uses the Spellbook's internal reflection to identify the spell.
- Parameters:
spell (Any) -- The class, function, or object instance to inspect.
aetheric_frame (str) -- The Aetheric Frame to search within. Defaults to "default".
Contract:
Delegates to the spellbook's frame-wide inspection, so it inherits that method's three-stage search and its habit of collapsing every failure into None.
A None result is therefore AMBIGUOUS between "not registered" and "lookup failed"; do not treat it as proof of absence.
- Threading:
Takes no lock of its own. Until 0.2.8232 it held the conduit lock across the spellbook call, which reaches frame locks (Aether._check_for_spell), while frame teardown takes the frame lock and then each conduit's lock (Conduit.permanent_cleanup): the two could hang each other. (lock_residuals, 0.2.8232)
- Lifecycle / Cleanup:
Guarded by check_cleaned(). A teardown of this conduit racing the call is unsupported, as for every Conduit lookup.
- Raises:
RuntimeError -- If the conduit has been cleaned.
- Returns:
The SHA256 unique ID of the spell if found, otherwise None.
- Return type:
Optional[str]
- begin_transaction(transaction_type: ChangeTransactionType, *, conduit_ids: Iterable[str] | None = None, conduits: Iterable[Conduit] | None = None, scope_keys: Iterable[str] | None = None, scope_hashes: Iterable[str] | None = None, binding_keys: Iterable[Tuple[str, str]] | None = None, contract_keys: Iterable[Tuple[str, str, str]] | None = None, metadata: Dict[str, Any] | None = None) None[source]ο
Public API
Begin a change-control transaction for this Conduit.
- Purpose:
Admit a mutation request through the frame-owned transaction mediator and, for bind transactions, open the bind-family transaction window.
Contract:
Only normal conduits may begin change-control transactions.
Admission is serialized by the mediator-owned change-control pipeline.
Bind transactions open the binding transaction window.
Link transactions must explicitly include the local conduit and peers.
Link and transfer transactions require dynamic mode.
- Parameters:
transaction_type -- Transaction type string value (e.g. "bind", "link").
conduit_ids -- Optional list of conduits participating in non-link requests. Link transactions require explicit conduit objects.
conduits -- Optional list of conduit objects participating in the request. For link transactions, include the local conduit and peers.
scope_keys -- Optional normalized scope keys. These ARE the admission vocabulary: they become the request's scope claims, and the moded claim table acquires and arbitrates them.
scope_hashes -- Optional normalized scope hashes. ADVISORY IDENTITY ONLY - they carry NO claims and are NOT checked for conflicts. Their only reader is the retired ChangeControlConflictManager, which nothing calls. Supplying hashes declares no overlap and buys no isolation; use scope_keys to declare scope.
binding_keys -- Optional binding keys affected by the request.
contract_keys -- Optional contract keys affected by the request.
metadata -- Optional structured metadata for diagnostics.
- Returns:
None.
- Raises:
RuntimeError -- If the Conduit is cleaned or not normal.
RuntimeError -- If change-control admission is denied.
RuntimeError -- If a link transaction omits required conduit objects.
ValueError -- If transaction_type is invalid.
TypeError -- If transaction_type has an invalid type.
- Threading:
Uses the Spellbook lock for local state; orchestrator handles admission state.
- end_transaction(transaction_type: ChangeTransactionType | None = None, *, success: bool = True) None[source]ο
Public API
End the active change-control transaction for this Conduit.
- Purpose:
Finalize an admitted change-control request through the mediator-owned transaction pipeline.
Contract:
Only normal conduits may end change-control transactions.
Raises if no change transaction is active.
- Parameters:
transaction_type -- Optional transaction type assertion for safety checks.
- Returns:
None.
- Raises:
RuntimeError -- If the Conduit is cleaned or not normal.
RuntimeError -- If no change transaction is active.
RuntimeError -- If transaction_type does not match the active request.
ValueError -- If transaction_type is invalid.
TypeError -- If transaction_type has an invalid type.
- Threading:
Uses the Spellbook lock for local state; orchestrator handles admission state.
- transaction(transaction_type: ChangeTransactionType, *, conduit_ids: Iterable[str] | None = None, conduits: Iterable[Conduit] | None = None, scope_keys: Iterable[str] | None = None, scope_hashes: Iterable[str] | None = None, binding_keys: Iterable[Tuple[str, str]] | None = None, contract_keys: Iterable[Tuple[str, str, str]] | None = None, metadata: Dict[str, Any] | None = None) Generator[Conduit, None, None][source]ο
Public API
Context-managed change-control transaction for this Conduit.
- Purpose:
Provide a safe begin/end wrapper for change-control transactions.
Contract:
Begins a change-control transaction on entry.
Ends the transaction on exit, even if an exception is raised.
Only normal conduits may enter this context.
Link transactions must explicitly include the local conduit and peers.
Link and transfer transactions require dynamic mode.
- Parameters:
transaction_type -- Transaction type string value (e.g. "bind", "link").
conduit_ids -- Optional list of conduits participating in non-link requests. Link transactions require explicit conduit objects.
conduits -- Optional list of conduit objects participating in the request. For link transactions, include the local conduit and peers.
scope_keys -- Optional normalized scope keys. These ARE the admission vocabulary: they become the request's scope claims, and the moded claim table acquires and arbitrates them.
scope_hashes -- Optional normalized scope hashes. ADVISORY IDENTITY ONLY - they carry NO claims and are NOT checked for conflicts. Their only reader is the retired ChangeControlConflictManager, which nothing calls. Supplying hashes declares no overlap and buys no isolation; use scope_keys to declare scope.
binding_keys -- Optional binding keys affected by the request.
contract_keys -- Optional contract keys affected by the request.
metadata -- Optional structured metadata for diagnostics.
- Yields:
Conduit -- The current Conduit instance for the duration of the transaction context.
- Raises:
RuntimeError -- If the Conduit is cleaned or not normal.
RuntimeError -- If change-control admission is denied.
RuntimeError -- If a link transaction omits required conduit objects.
ValueError -- If transaction_type is invalid.
TypeError -- If transaction_type has an invalid type.
- Returns:
- A context manager yielding this conduit
inside a held change-control transaction window.
- Return type:
Generator[Conduit, None, None]
- add_bind_hooks(*, pre: Sequence[Callable[[Any], object]] | None = None, activation: Sequence[Callable[[Spell], object]] | None = None, post: Sequence[Callable[[Spell], object]] | None = None) None[source]ο
Register bind lifecycle callbacks on this normal conduit's owning Spellbook.
- Purpose:
Expose the same registration customization through the Conduit that already facades bind and bind_inactive, using one Book-owned registry.
Contract:
Requires a live normal conduit. Lessers borrow a Book and cannot change its bind-hook policy through this facade.
Delegates unchanged to Spellbook.add_bind_hooks. Sequences append in order; all supplied callbacks are validated before mutation.
Pre receives the incoming reference and rejects by raising. Activation receives the actual newly constructed Spell; post receives the completed active or parked registration before outer transaction commit. Callback return values are ignored.
Updates affect subsequent binds through either the Book or Conduit; an in-flight bind retains its captured callback set.
Hook setup follows Book's live-update contract independently of configuration freeze. It does not enable binding when the frame's existing bind admission rules prohibit it.
Existing Conduit/Meld runtime hooks and per-Spell creation hooks remain separate. Recording and cleanup stay with the owning Book.
- Parameters:
pre -- Ordered synchronous reference-checking callbacks.
activation -- Ordered callbacks receiving the new Spell definition.
post -- Ordered callbacks receiving the completed binding.
- Threading:
Adds no Conduit lock or transaction window around delegation. The Book/Bind owner coordinates registry updates and recording.
- Returns:
None.
- Raises:
RuntimeError -- If the conduit is cleaned or is not normal.
TypeError -- If the owning Book rejects a non-callable callback.
- clear_bind_hooks() None[source]ο
Clear all bind lifecycle callbacks from this normal conduit's owning Book.
Contract:
Requires a live normal conduit; lessers cannot clear the borrowed Book's registration policy.
Delegates to Spellbook.clear_bind_hooks. Future Book/Conduit binds see the empty registry; in-flight binds keep their captured set.
Leaves existing Spell creation hooks and Conduit/Meld runtime hooks unchanged. Does not dispose user callbacks or existing creations.
The Book refreshes recording markers where applicable. Setup and clearing do not change actual bind admission or frame posture.
- Threading:
Delegates without an additional Conduit lock or transaction. Callback storage, synchronization and recording remain owned by Book/Bind.
- Returns:
None.
- Raises:
RuntimeError -- If the conduit is cleaned or is not normal.
- bind(*, spell: Any, existence: str | Existence, permissions: str = 'create', spellframe: Any = None, binding_name: str | None = None, profile: str = 'general', resolvable: bool = True, managed_spell_mode: ManagedSpellMode | str | None = None, managed_spell_limit: int | None = None, managed_spell_timeout_seconds: float | None = None, managed_spell_reset_methods: Sequence[str] | None = None, **kwargs: Any) str[source]ο
Bind a spell into the Spellbook for future instantiation and dependency injection.
- Purpose:
Register one class, function, lambda, or existing object through this conduit's Spellbook so later meld work can resolve it by spell identity, (spellframe, binding_name) lookup key, and lifecycle policy.
Contract:
Only normal conduits may bind spells.
Requires an active binding transaction.
Delegates the actual bind pipeline to the owning Spellbook and returns the resulting spell_id.
Propagates lifecycle hooks only after validating that supplied hook values are callable.
Permissions:
read lets other conduits consume the spell but not create new instances.
create lets other conduits consume and instantiate the spell.
block restricts access to the owning conduit.
Lookup semantics:
spellframe provides the primary namespace or grouping key.
binding_name provides the secondary disambiguation key inside that frame.
Optional lifecycle hooks (**kwargs):
pre_hooks
activation_hooks
post_hooks
- Parameters:
spell (Any) -- The class, function, lambda, or existing object to register.
existence (Existence) -- Lifecycle scope for the spell.
permissions (str) -- Permission level exposed to other conduits (read, create, or block).
spellframe -- Logical interface, frame, or grouping key for the spell.
binding_name -- Secondary key used to distinguish this spell among others in the same frame.
profile (str) -- Spell profile family to attach after bind completion.
resolvable (bool) -- Native per-version resolution capability, forwarded unchanged to Spellbook. Defaults to True; False retains existing binding and lifetime rules.
managed_spell_mode (Optional[Union[ManagedSpellMode, str]]) -- Pool policy of an Existence.managed_spell_quantity binding (elastic by default), forwarded unchanged to Spellbook, which validates it with the other three.
managed_spell_limit (Optional[int]) -- elastic: the most idle objects kept (default 256); limited_quantity and queue: the most objects alive at once (required).
managed_spell_timeout_seconds (Optional[float]) -- queue only, required there: how long a lease waits for a release.
managed_spell_reset_methods (Optional[Sequence[str]]) -- Zero-argument methods of the class run, in order, on every release. The four managed options must stay None on any other existence.
**kwargs -- Optional lifecycle hooks and related bind-time metadata.
- Returns:
The unique SHA256 spell_id associated with the bound spell.
- Return type:
str
- Raises:
RuntimeError -- If the conduit is cleaned, is not normal, no binding transaction is active, or the spell collides with an existing registry entry.
TypeError -- If invalid hook types or a non-bool resolvable value are provided, a managed option has the wrong type, or a managed binding targets a non-class.
ValueError -- If a managed option is malformed or set on another existence.
- bind_inactive(*, spell: Any, spell_index: Any, existence: str | Existence, permissions: str = 'create', spellframe: Any = None, binding_name: str | None = None, profile: str = 'general', resolvable: bool = True, managed_spell_mode: ManagedSpellMode | str | None = None, managed_spell_limit: int | None = None, managed_spell_timeout_seconds: float | None = None, managed_spell_reset_methods: Sequence[str] | None = None, **kwargs: Any) str[source]ο
Public API
Stage a spell as an INACTIVE member of an existing owned spell_index, off the resolution surface, for later activation via notch_spell.
- Purpose:
Create a spell and park it as an inactive candidate on an existing index in one call, so a later notch can promote it. This is the index-aware sibling of bind (which always activates its spell on a freshly minted index).
Contract:
Only available in a dynamic environment; raises otherwise.
Only normal conduits may stage spells.
Delegates to the owning Spellbook's bind_inactive surface.
EVERY VERSION OF AN INDEX IS BOUND THE WAY ITS FIRST VERSION WAS (2026-10-25): the same kind of spellframe (none, a string category, a Protocol) and the same address (spellframe and binding name, case-insensitive). Stage an edited class with the index's spellframe and binding_name; a renamed class or a new binding name is a new spell - bind it on its own. A version bound another way, or an index another Spellbook owns, is refused before anything is registered.
Change-control transaction admission for this staging op is owned by the conduit/mediator lane (wired separately); this facade performs the dynamic gate and delegation only, holding no transaction window.
- Parameters:
spell (Any) -- The class, function, lambda, or existing object to register.
spell_index (Any) -- The already-owned SpellIndex to attach the inactive spell to.
existence (Union[str, Existence]) -- Lifecycle scope for the spell.
permissions (str) -- Permission level exposed to other conduits (read, create, or block).
spellframe (Any) -- Logical interface/frame grouping key for the spell.
binding_name (Optional[str]) -- Secondary disambiguation key within the frame.
profile (str) -- Spell profile family to attach after bind completion.
resolvable (bool) -- Native capability of this parked version, forwarded unchanged to Spellbook. Defaults to True and is independent of active index selection.
managed_spell_mode (Optional[Union[ManagedSpellMode, str]]) -- Pool policy of an Existence.managed_spell_quantity binding (elastic by default), forwarded unchanged to Spellbook, which validates it with the other three.
managed_spell_limit (Optional[int]) -- elastic: the most idle objects kept (default 256); limited_quantity and queue: the most objects alive at once (required).
managed_spell_timeout_seconds (Optional[float]) -- queue only, required there: how long a lease waits for a release.
managed_spell_reset_methods (Optional[Sequence[str]]) -- Zero-argument methods of the class run, in order, on every release. The four managed options must stay None on any other existence. A parked managed version keeps its own options.
**kwargs -- Optional lifecycle hooks (pre/activation/post).
- Returns:
The SHA256 spell_id of the parked inactive spell.
- Return type:
str
- Raises:
RuntimeError -- If the conduit is cleaned, is not normal, the dynamic environment is not enabled, or there is no owning Spellbook; from the Spellbook, if spell_index is another Spellbook's (nothing is registered).
TypeError -- If resolvable is not a bool or Bind rejects the target (a managed option of the wrong type or a managed non-class included).
ValueError -- If a managed option is malformed or set on another existence, or the version is bound another way than spell_index's versions (the message names both bindings and the remedy; nothing is registered).
- scan(module: ModuleType) list[str][source]ο
Public API
Scan a module for scan_bind-decorated objects and bind them into this Conduit's Spellbook.
This is a module-only scan: it does not traverse packages or import submodules. Any object marked with scan_bind must originate from the scanned module, otherwise the scan fails.
If a binding transaction is already active on the owning Spellbook, this call reuses that transaction window. Otherwise the conduit opens and closes its own binding transaction around the scan so direct conduit-side scans remain transaction-correct.
Contract:
NORMAL CONDUITS ONLY: a lesser or pooled conduit raises rather than scanning, checked before any posture rule.
Then posture-gated - refused when the frame disables the bind family, which includes post-conjure scanning on a non-dynamic frame.
Reuses an already-active binding transaction when one exists; otherwise opens and closes its own, so a direct conduit-side scan is always transaction-correct.
- Parameters:
module (ModuleType) -- The module to scan for decorated spell targets.
- Returns:
Spell IDs bound during the scan, in module dict order.
- Return type:
list[str]
- Raises:
RuntimeError -- If the Conduit is cleaned or not normal.
RuntimeError -- If an incompatible change transaction is already active.
TypeError -- If module is not a module or metadata is invalid.
ValueError -- If a decorated object is not owned by the module.
RuntimeError -- Propagated from Spellbook.bind on binding errors.
- get_spell_permissions(spell_id: str) str | None[source]ο
Public API
Get the permissions for a spell by its spell_id, within this conduit. This returns the access level ("read", "create", "block") defined when the spell was bound.
Contract:
LOCAL ONLY. It resolves through THIS conduit's spellbook (Spellbook.find_spell_by_spell_id), so a spell reachable by contract from a peer conduit is NOT found here.
EXACT: the spell_id names one spell, active or parked, and the answer is the permissions THAT spell was bound with. Until 0.2.8253 it matched by SpellIndex, and a parked spell_id answered the permissions of the spell its index had active.
Lock-free (0.2.8230): the lookup answers from the Book's id maps instead of walking its live index map under the conduit lock, which a concurrent bind or removal could resize mid-walk.
NEVER RETURNS None despite the Optional[str] annotation: a miss RAISES RuntimeError. Treat the annotation as wrong and the Raises block as authoritative.
Returns the permission enum's .name STRING, not the enum member.
- Parameters:
spell_id (str) -- The spell_id (SHA256) of the spell, active or parked.
- Returns:
The permissions the spell was bound with.
- Return type:
Optional[str]
- Raises:
RuntimeError -- If the spell with the given ID is not found in the spellbook.
- property mutation_research: MutationResearchο
Return the Aether-hosted MutationResearch WORLD root.
- Purpose:
Accessor door (owner ruling 2026-07-12): hand back the one process-wide research root from the conduit, mirroring how this conduit already carries _crystallizer from its owning spellbook.
Contract:
The reference is BORROWED and world-scoped: it is the exact object Aether().mutation_research returns, never a conduit-scoped view. This conduit never cleans it.
The door only returns the object. Activation, liveness, and recording gates are enforced by the root's own verbs; an inactive root refuses research work itself.
Bound once at __init__ from the owning spellbook; lesser conduits share the same root through the shared book. The reference is deleted during cleanup.
- Returns:
The hosted mutation-research singleton root.
- Return type:
- Raises:
RuntimeError -- If the conduit has been cleaned.
- transfer_spell_ownership(*, spell: Spell | __annotationlib_name_1__ | SpellIndex, target_conduit: Conduit, move_creations: bool = True, include_dependencies: bool = False, force_unshare: bool = True, invalidate_after_transfer: bool = True, mark_dependencies_dirty: bool = False) dict[source]ο
Public API (dynamic mode)
Transfer stewardship of a spell to another conduit.
Contract:
The spell's whole SpellIndex moves: the index, with its active and parked members, leaves this conduit's Spellbook and frame registry entry and joins the target's. The target becomes the spell's owner, so a unique instance lives in the target's store from then on, and this conduit can no longer meld the spell.
Existing instances follow move_creations (below). A transfer never disposes anything.
A transfer hands over stewardship, not a working setup. The spells the transferred spell depends on stay with this conduit unless include_dependencies moves the direct ones, so the target can start out broken: a moved instance keeps the dependencies it was built with, and this conduit's teardown disposes the ones it owns while the moved instance still holds them. That is expected in a runtime agents iterate in. The target purges what it does not want, binds the dependencies it needs (a meld that must build the spell without them raises UnresolvedInputError naming each missing input) and melds its own version, while this conduit cleans up its own scope.
Borrowers are unshared (force_unshare) or repointed at the target; with include_dependencies, each direct dependency this conduit owns is transferred with the same options.
Uses the normal TRANSFER_OWNERSHIP transaction path before the existing TransferOfOwnership execution helper runs.
Keeps request planning and admission in the mediator/strategy layer while leaving the irreversible runtime move in the transfer helper for now.
- Parameters:
spell -- Spell object, spell_id, or SpellIndex to transfer.
target_conduit -- The conduit that will become the new steward.
move_creations -- True (the default since 0.2.8239): the instances this conduit's store holds for every member of the spell's index move into the target's store with the spell. A unique stays one object: whatever already holds it keeps the instance the target now serves. The many objects a moved holder was built with do not move: they stay recorded in the store that built them, which disposes them when it ends (the owner's decision, 2026-10-24; from 0.2.8238 to 0.2.8265 they moved with the holder). A moved entry replaces whatever the target's store already holds under that spell id; the replaced instances are not disposed. False: nothing moves. The active member's instances are taken out of this conduit's store and kept only until the transfer has finished (for its rollback); they are neither moved nor disposed, Melder stops tracking them, and the target builds its own on its next meld - for a unique, a second instance beside any that the application or other objects still hold. Either way, unique_per_conduit_lineage instances stay where they were resolved, and spellspace-local and cluster instances are not in this conduit's store, so a transfer never touches them.
include_dependencies -- If True, also transfer each direct dependency this conduit owns, with the same options, so the target receives those spells (and, with move_creations, their instances) instead of depending on this conduit for them.
force_unshare -- If True, strip all contracts/shares for this spell during transfer.
invalidate_after_transfer -- If True, mark the moved SpellIndex dirty after transfer.
mark_dependencies_dirty -- If True, mark the dependencies' indexes dirty (even if not moved).
- Returns:
Preflight summary of the transfer plan.
- Return type:
dict
- enable_meld() None[source]ο
Public API
Enable meld execution for this conduit lineage.
- Purpose:
Release any blocked meld calls and allow new melds to proceed.
Contract:
Delegates to the local CreationGate for this conduit.
Gate governance is provided by DevOps CreationGateController.
- Raises:
RuntimeError -- If the Conduit has been cleaned.
- Returns:
None.
- disable_meld() None[source]ο
Public API
Disable meld execution for this conduit lineage.
- Purpose:
Block meld calls until enable_meld() is invoked.
Contract:
Delegates to the local CreationGate for this conduit.
Gate governance is provided by DevOps CreationGateController.
- Raises:
RuntimeError -- If the Conduit has been cleaned.
- Returns:
None.
- 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) Any | None[source]ο
Public API
Direct spell activation facade for this Conduit.
At the Conduit boundary, meld supports multiple root entry modes.
Callers may resolve by:
spell as a string (treated as a human SpellName), or
spell as a spell object (class/function/Protocol), or
spell_id as the canonical machine identity, or
spellframe as a frame/protocol (or string frame key), or
an explicit spellframe/binding address.
- Call shape:
spell is the human-facing positional parameter. A string such as "MyService" resolves by logical SpellName. Machine callers use keyword-only spell_id=..., which is forwarded positionally into the internal door's existing ID fast lane.
These inputs are normalized and delegated to the underlying Meld instance, which resolves a concrete spell_id via SpellInputUtils.
Resolution, reuse, and lifecycle behavior are delegated to the underlying Meld instance.
In dynamic mode, this method uses the Conduit's CreationGate to control meld entry and track active meld tickets. In automatic mode, meld bypasses gate checks for a minimal hot path.
Gate/ticketing behavior (dynamic mode only):
If the gate is terminally closed, raises immediately.
If the gate is disabled, blocks until re-enabled, then re-checks closure.
Registers a meld ticket for the duration of the call so the gate can track active work and drain safely during shutdown.
Contract:
HUMAN AND MACHINE IDENTITIES ARE DISTINCT: positional strings are logical SpellNames; opaque SHA identities use spell_id=. Concrete spell objects and spellframe/binding addresses remain supported.
spell_id= is forwarded directly into the internal positional ID fast lane and never enters human-name normalization.
On an automatic conduit an id meld (plain, or with a non-empty dict override) is served here from the meld door's fast-door entry when every fast-door guard holds (2026-09-26); results are identical to the door's, and any miss continues in the door's id lane. A plain id meld of an existing-object spell returns its bound object there without calling the existing-creation door.
On an automatic conduit a meld by registered name (meld("Name")) or by class (meld(spell=Cls)) with no spellframe or binding_name is served the same way from the door's name/class registry (2026-09-27), with the same guards and arms; the entry is minted by the door after one successful meld of that shape, so results, errors and lifetimes are the door's. A miss, an unhashable spell, an instance or a callable as spell continue in the door.
GATING IS MODE-DEPENDENT: in dynamic mode entry runs through the creation gate and is ticketed; in automatic mode the gate is BYPASSED entirely for a minimal hot path. The same call therefore has different concurrency behaviour per frame posture.
A DISABLED GATE BLOCKS rather than failing: the call waits until the gate is re-enabled and then re-checks closure. A TERMINALLY CLOSED gate raises immediately. Distinguish the two - one is back-pressure, the other is refusal.
Resolution, reuse and lifetime are delegated to the Meld runtime and governed by the spell's Existence, not by this call.
- Parameters:
spell -- Human-facing target. Strings are logical SpellNames; classes, functions, and Protocols participate in key normalization.
spell_id -- Optional canonical SHA256 machine identity. Mutually exclusive with spell and delegated directly to the internal ID lane.
spellframe -- Optional spellframe / protocol / string frame key used for resolution. If provided, it becomes the primary frame key.
binding_name -- Optional binding name (string) associated with the spell. Used as the binding key during resolution.
override -- Optional per-call override payload (dict / list / tuple) passed through to Meld.meld for constructor/factory argument overrides.
- Returns:
The resolved component instance (reused or newly created) as returned by Meld.meld.
- Return type:
Any
- Raises:
RuntimeError --
If the Conduit has been cleaned. - If the underlying Meld instance is missing. - If the CreationGate is closed.
ValueError --
If none of spell, spell_id, or spellframe are provided. - If both spell and spell_id are provided.
TypeError --
If spell_id is not a string when provided. - If binding_name is not a string when provided.
KeyError -- Propagated from Meld.meld when a spell_id cannot be resolved.
NotImplementedError -- Propagated from Meld.meld for spell types or existence modes not yet implemented.
HookExecutionError -- Propagated from Meld.meld if hook execution fails.
- managed_spell_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) ManagedSpellLease[Any][source]ο
Public API
Meld one managed spell and return its object as a lease that gives it back.
- Purpose:
The meld-plus-release form of Existence.managed_spell_quantity (managed_spell_quantity S5, 2026-10-15): with conduit.managed_spell_meld(Logger) as logger: leases a pooled object and puts it back when the block exits, as ReleaseManagedSpell().release(logger) would.
Contract:
Takes meld's inputs - a SpellName string, a class, spell_id=, or a spellframe/binding address - and resolves the target as meld does. A target of any other existence is refused before anything is melded or leased.
The pool is the resolved version's pool in its owner root's store, read before the meld; a version with no owner store, or a store without that pool, is refused with the missing-pool error.
The object comes from a meld of the resolved version by id: an idle object, else one built into a place the pool reserves (limited_quantity and queue apply their mode there).
The lease releases once (release(), or the end of the with block, which never suppresses the block's exception). Nothing releases it otherwise: an object never released holds its place until its root is torn down.
With override, keys on the managed spell's own parameters build a fresh object the pool never counted; the lease still puts it into the pool when released, as releasing any object of the class does.
- Parameters:
spell -- A SpellName string, or the managed class.
spell_id -- The managed version id; exclusive with spell.
spellframe -- Optional spellframe used for resolution.
binding_name -- Optional binding name used for resolution.
override -- Optional override payload passed to the meld.
- Returns:
The leased object (.object, or the with target) and its pool.
- Return type:
- Raises:
ValueError -- When both spell and spell_id are given, no identity is given, or the target is not Existence.managed_spell_quantity.
TypeError -- When spell_id is not a string.
KeyError -- When no spell resolves.
MeldExecutionError -- When the version has no pool to lease from; the pool's ManagedSpellExhaustedError (limited_quantity at its limit, queue at its timeout); anything the meld raises.
RuntimeError -- When the conduit is cleaned, or the pool was torn down with its root.
- 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 through this conduit.
- Purpose:
Expose targeted disposal without ending the conduit or removing the binding. Identity normalization mirrors this facade's meld method.
Contract:
Delegates discovery and authority to the owned ConduitMeld door.
Many and per-conduit creations are local. Unique requires the binding owner, lineage the lineage root, and cluster its leader.
Never redirects into an active SpellSpace; use that space's purge.
Preserves the binding, compiled context, conduit and pools.
A spell_id reaches any version this conduit can see - its Book's own or a borrowed copy, active or parked - so a version a notch parked is purged without a notch back; every other selector names the version an index has active, as meld does.
- 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, this conduit's Book's own or a borrowed copy - and its entries in the authorized store.
spellframe -- Optional frame/type used by ordinary binding discovery.
binding_name -- Optional named binding within the selected frame.
purge_all -- True removes all retained target entries. False requires an instance as spell and removes only that object from the store.
- Returns:
Removed creation count; zero when no matching entry is retained in the authorized store. Untracked many results cannot be purged.
- 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 conduit can see carries the spell_id, or normal meld discovery cannot find the binding.
RuntimeError -- If cleaned, the cluster is inert, this conduit lacks authority, or a unique version has no owner store.
TypeError -- If purge_all is not a bool.
ExceptionGroup -- Disposal failures after selected entries have been removed.
- Threading / Concurrency:
Creations coordinates removal with the existing creation writer locks and runs disposal after releasing them. This call does not drain in-flight resolution or perform an ownership transaction.
- Lifecycle / Cleanup:
Existing application references remain valid Python references; they are not rewritten or revoked. Supplied objects also remain on their registration. Scope ownership must remain live for this call.
- meld_existing_spell(spell_name: str | None = None, *, spell: str | object | None = None, spellframe: str | object | None = None, binding_name: str | None = None) Any[source]ο
Public API
Return an already-existing live object for one resolved spell.
- Purpose:
Expose the cold-path reuse-only runtime operation without adding branches to the hot meld(...) path.
Contract:
The pre-resolved counterpart to meld: it skips input normalization because the spell is already identified, and is the path used when a caller already holds the object.
Shares meld's gate behaviour exactly - ticketed through the creation gate in dynamic mode, bypassed in automatic mode - so the same blocking-versus-raising distinction applies.
- Parameters:
spell_name -- Logical spell name (string). When provided without an explicit spell or spellframe, this is treated as the name-based key for resolution.
spell -- Primary spell identifier as spell id string or spell object.
spellframe -- Optional spellframe / protocol / string frame key used for resolution.
binding_name -- Optional binding name associated with the spell.
- Returns:
Existing live runtime object for the resolved spell.
- Return type:
Any
- Raises:
RuntimeError --
If the Conduit has been cleaned. - If the underlying Meld instance is missing. - If the CreationGate is closed.
ValueError -- If the resolved spell is not currently live.
RuntimeError -- If the lifecycle does not support deterministic existing-object retrieval.
- has_live_creation(spell_name: str | None = None, *, spell: str | object | None = None, spellframe: str | object | None = None, binding_name: str | None = None) bool[source]ο
Public API
Resolve a spell through the same identity path as meld(...), but only report whether a live creation already exists.
- Purpose:
Provide one no-create runtime probe that later static-access code can use to decide whether an object is already available without entering the meld creation path.
Contract:
Mirrors the root identity inputs accepted by meld(...), with one difference: a spell_id given as spell names exactly that version, active or parked, this conduit's Book's own or a borrowed copy, so a version a notch parked is answered for without a notch back.
Delegates all lookup and existence semantics to the owned Meld instance.
Never creates, registers, links, or mutates objects.
Does not interact with the dynamic creation gate, because the method is observational only.
- Parameters:
spell_name -- Optional logical spell name for name-based resolution.
spell -- Optional spell id string or spell object used for resolution.
spellframe -- Optional spellframe / protocol / frame key used for resolution.
binding_name -- Optional binding name used for lookup-key resolution.
- Returns:
True when the resolved spell already has a live creation in the relevant runtime scope.
- Return type:
bool
- Raises:
RuntimeError -- If the Conduit has been cleaned or the underlying Meld instance is unavailable.
ValueError -- If none of spell_name, spell, or spellframe are provided.
KeyError -- Propagated from Meld when a spell cannot be resolved: for a spell_id, when no version this conduit can see carries it.
- describe_live_creation_status(spell_name: str | None = None, *, spell: str | object | None = None, spellframe: str | object | None = None, binding_name: str | None = None) Dict[str, Any][source]ο
Public API
Resolve a spell through the same identity path as meld(...), but return structured live-creation status for this conduit context.
- Purpose:
Provide a richer diagnostic/runtime query surface over the same no-create probe used by has_live_creation(...).
Contract:
Mirrors the root identity inputs accepted by meld(...), with one difference: a spell_id given as spell names exactly that version, active or parked, this conduit's Book's own or a borrowed copy, and the payload's spell_id is that version's.
Delegates all lookup and existence semantics to the owned Meld instance.
Never creates, registers, links, or mutates objects.
Reports the query as scoped to this conduit context.
- Parameters:
spell_name -- Optional logical spell name for name-based resolution.
spell -- Optional spell id string or spell object used for resolution.
spellframe -- Optional spellframe / protocol / frame key used for resolution.
binding_name -- Optional binding name used for lookup-key resolution.
- Returns:
Structured live-creation status payload.
- Return type:
Dict[str, Any]
- Raises:
RuntimeError -- If the Conduit has been cleaned or the underlying Meld instance is unavailable.
ValueError -- If none of spell_name, spell, or spellframe are provided.
KeyError -- Propagated from Meld when a spell cannot be resolved: for a spell_id, when no version this conduit can see carries it.
- describe_spells_in_conduit() list[dict[str, Any]][source]ο
Public API
Return a user-facing dump of spell targeting details visible through this conduit's Spellbook.
- Purpose:
Expose the Spellbook-owned ACL-authoring dump on the conduit surface so advanced Rift and conduit users can inspect the visible spell set without reaching into the Spellbook directly.
Contract:
Delegates to the owned Spellbook.
Returns detached dictionaries only.
Does not create, mutate, or resolve objects.
- Returns:
Spell targeting details currently visible through this conduit's Spellbook.
- Return type:
list[dict[str, Any]]
- Raises:
RuntimeError -- If the Conduit has been cleaned or the underlying Spellbook is unavailable.
- link(target_conduit: Conduit) bool[source]ο
Public API
Attempts to establish a link between this Conduit and a target_conduit.
Linking is only allowed if the world is in dynamic mode. This process initiates a contract relationship between the two conduits based on the current policy.
- Admission:
The link is admitted through the frame-owned change-control transaction mediator as a self-admitted link transaction (the same shape sever_link uses for unlink): the transaction is started before the ward mutation, the ward mutation runs inside the transaction window under the conduit lock, and the transaction ends with success=False when the mutation raises.
On success, the following hook will be fired on this Conduit (if configured):
- "on_conduit_post_link(self, target_conduit)"
Contract:
NORMAL CONDUITS ONLY and DYNAMIC MODE ONLY; both are refused before any transaction is opened.
THE CHEAP GUARDS RUN BEFORE ADMISSION - self-link, lesser target, and cross-frame target are all rejected before the transaction starts, so an invalid link never consumes a transaction window.
Self-admitted link transaction, the same shape sever_link uses for unlink: started before the ward mutation, the mutation runs inside the window under the conduit lock, and the transaction ends with success=False if the mutation raises.
Fires on_conduit_post_link only on success.
- Parameters:
target_conduit (Conduit) -- The target Conduit to link to.
- Returns:
True if the linking process succeeds.
- Return type:
bool
- Raises:
RuntimeError -- If the Conduit is cleaned.
RuntimeError -- If dynamic environment is not enabled.
RuntimeError -- If change-control admission is denied by the mediator.
TypeError -- If target_conduit is not an Conduit instance.
RuntimeError -- If the target conduit does not have a valid creation context.
RuntimeError -- If linking this conduit to itself (guarded before transaction admission; the link strategy requires two distinct participants).
RuntimeError -- If the target is a lesser conduit (guarded before transaction admission; lineage attachment is not a peer link).
RuntimeError -- If the target conduit belongs to a different AethericFrame.
- notch_spell(*, spell_index: Any, spell: Any = None, spell_id: str | None = None, change_reason: SpellStateChangeReason = SpellStateChangeReason.selected_different_spell) Any[source]ο
Public API
Conduit facade for a SpellIndex notch: make one version of an index its active (resolvable) member. This conduit admits the notch change-control transaction and the owning Spellbook makes the switch inside the held window.
- Purpose:
Promote a staged version - the notch in stage -> notch -> meld - or go back to a parked one. Name it by spell_id, the spell_id bind or bind_inactive returned, or by its Spell object.
Contract:
DYNAMIC MODE ONLY; refused on an automatic frame.
EXACTLY ONE TARGET: spell_id or spell. A spell_id is resolved inside this call to the exact spell this conduit's Spellbook owns, active or parked - the spell get_spell_by_spell_id returns for it (until 0.2.8253 get_spell_by_id answered a parked spell_id with the index's ACTIVE spell).
THE TARGET IS CHECKED before the transaction starts and again inside the held window: it must be a version this conduit's Spellbook owns and a member of spell_index. The second check runs under the notch seal (the Spellbook and its conduits claimed EXCLUSIVE), so no other index operation can move the target between that check and the switch. A refused call changes nothing.
REPOINTS THE ACTIVE MEMBER of an existing index - it does not create, bind or remove anything. The previous member stays in the index, parked, and a notch back by its spell_id restores it.
Notching to the index's active version is a no-op: nothing moves and no borrower is touched.
A VERSION THAT FAILS ITS STRUCTURAL CHECK IS REFUSED WITH NOTHING MOVED (2026-10-19): a version never compiled is checked (phases 1-4) inside the held window once it is active, and when the check fails the Spellbook puts the structure back before this call raises - the index selects the version it selected, that version stays active, claimed and routed, the refused one is parked again with no verdict kept, nothing is journaled or published for it, and no borrower is touched. A retry is checked, and refused, again.
A NOTCH NEVER MOVES THE INDEX'S ADDRESS (2026-10-25): every version of an index is bound at the index's address, so the switch moves the address's claim from the outgoing version to the incoming one. An address another spell holds - another index's active version of this Spellbook (a version split off with remove_from_spell_index while its source still serves the address) or another Spellbook's spell - refuses the notch with a RuntimeError naming the holder, before anything moves.
After the window, every linked peer parks its copy of the outgoing version, a peer holding a parked copy of the incoming version (a grant of that version) has it made active again, and index-link borrowers move to the new one. The consumers of every copy that changed are marked and revalidate at their next meld; objects already built keep what they were built with (rule 2, 2026-10-16).
The default change_reason is selected_different_spell, which records an ordinary selection rather than a mutation. Pass a mutation reason explicitly when that is what happened, because this default will otherwise misattribute the change in the state history.
Admitted as a notch change-control transaction by this conduit, so it participates in change control rather than bypassing it.
- Parameters:
spell_index -- The SpellIndex whose active member is switched.
spell -- The spell to make active, as a Spell object; exclusive with spell_id.
spell_id -- The spell_id of the spell to make active, as bind or bind_inactive returned it; exclusive with spell.
change_reason -- Why the active member was repointed; defaults to selected_different_spell (general selection, not a mutation).
- Returns:
The now-active Spell (the owning Spellbook's notch result).
- Return type:
Any
- Raises:
SpellbookValidationError -- When the version fails its structural check. Its first line says the notch did not happen and names the version still active; the validation report follows. Nothing has moved.
ValueError -- When both or neither of spell and spell_id are given; when the spell is not owned by this conduit's Spellbook (a spell_id nothing here bound, a disposed spell, another Book's spell); when it belongs to another SpellIndex.
TypeError -- When spell_id is not a string, or a string is given as spell.
RuntimeError -- If the Conduit is cleaned, the frame is not dynamic, or the Conduit has no owning Spellbook; when another spell holds the index's address (the message names its spell_id and the remedy; nothing moved); and whatever the transaction or the switch raises, including a reversal of a refused notch that fails (a Melder bug; the message names both versions).
Example
# ReportService edited: the same class name and binding as the index's versions. id_v2 = conduit.bind_inactive(spell=ReportService, spell_index=index, existence="unique") conduit.notch_spell(spell_index=index, spell_id=id_v2) conduit.meld(spell_id=id_v2) # the edited ReportService
- add_to_spell_index(*, spell: Any = None, spell_id: str | None = None, target_index: Any) Any[source]ο
Public API
Conduit facade for moving a parked spell onto another SpellIndex of this conduit's Spellbook. This conduit admits the add_to_index change-control transaction and the owning Spellbook moves the spell inside the held window.
- Purpose:
Move a staged (parked) spell into another SpellIndex, ahead of a notch to it there. Name it by spell_id, the spell_id bind or bind_inactive returned, or by its Spell object.
Contract:
DYNAMIC MODE ONLY; refused on an automatic frame with a logged RuntimeError.
EXACTLY ONE SPELL: spell_id or spell. A spell_id is resolved inside this call to the exact spell this conduit's Spellbook owns, active or parked - the spell get_spell_by_spell_id returns for it (until 0.2.8253 get_spell_by_id answered a parked spell_id with the index's active spell).
ONLY A PARKED SPELL MOVES: the Spellbook refuses an active spell (notch away from it first), a spell it does not own, and a target_index it does not own.
ONLY A SPELL BOUND THE WAY THE TARGET'S VERSIONS ARE MOVES (2026-10-25): every version of an index is bound the way its first version was, so a spell bound with another kind of spellframe or at another address is refused (ValueError) before anything moves. A version split off with remove_from_spell_index keeps its binding and can be moved back.
Adds a version to the index WITHOUT making it active - selection is a separate notch_spell step, so adding is safe to do ahead of a switch.
The spell leaves its current index, and an index the move empties is destroyed. After the window, index-link borrowers gain the member on the target and lose it on the source (or drop the destroyed index).
- Parameters:
spell -- The parked spell to move, as a Spell object; exclusive with spell_id.
spell_id -- The spell_id of the parked spell to move, as bind or bind_inactive returned it; exclusive with spell.
target_index -- The index to move it onto.
- Returns:
The moved Spell (the owning Spellbook's result).
- Return type:
Any
- Raises:
ValueError -- When both or neither of spell and spell_id are given, or when this conduit's Spellbook owns no spell under spell_id; nothing is started.
TypeError -- When spell_id is not a string, or a string is given as spell.
RuntimeError -- If the Conduit is cleaned, the frame is not dynamic, or the Conduit has no owning Spellbook; from the Spellbook, if the spell is not owned there, is active, or target_index is not an index it owns.
ValueError -- From the Spellbook, inside the window, if the spell is bound another way than target_index's versions; nothing moves.
Example
# A version split off into an index of its own moves back into its index: conduit.remove_from_spell_index(spell_id=id_v2, source_index=index) conduit.add_to_spell_index(spell_id=id_v2, target_index=index) conduit.notch_spell(spell_index=index, spell_id=id_v2)
- remove_from_spell_index(*, spell: Any = None, spell_id: str | None = None, source_index: Any) Any[source]ο
Public API
Conduit facade for separating a parked spell out of its index into a fresh one. This conduit admits the remove_from_index change-control transaction and the owning Spellbook splits the spell out inside the held window.
- Purpose:
Take a staged (parked) spell out of its SpellIndex, into an index of its own. Name it by spell_id, the spell_id bind or bind_inactive returned, or by its Spell object.
Contract:
DYNAMIC MODE ONLY; refused on an automatic frame with a logged RuntimeError.
EXACTLY ONE SPELL: spell_id or spell, resolved as add_to_spell_index resolves it.
ONLY A PARKED MEMBER IS SPLIT OUT: the Spellbook refuses an active spell (notch away from it first, so the selection never names a non-member), a spell it does not own, a spell that is not a member of source_index, and the index's only member (cleanup_spell disposes that).
The spell becomes the only member of a fresh index and stays parked; the source keeps its other members and its selection, and nothing is destroyed. After the window, index-link borrowers drop the member.
- Parameters:
spell -- The parked spell to split out, as a Spell object; exclusive with spell_id.
spell_id -- The spell_id of the parked spell to split out, as bind or bind_inactive returned it; exclusive with spell.
source_index -- The index the spell belongs to.
- Returns:
The separated Spell (the owning Spellbook's result).
- Return type:
Any
- Raises:
ValueError -- When both or neither of spell and spell_id are given, or when this conduit's Spellbook owns no spell under spell_id; nothing is started.
TypeError -- When spell_id is not a string, or a string is given as spell.
RuntimeError -- If the Conduit is cleaned, the frame is not dynamic, or the Conduit has no owning Spellbook; from the Spellbook, if the spell is not owned there, is active, is not a member of source_index, or is its only member.
- cleanup_spell(*, spell: Any) None[source]ο
Public API
Conduit facade for fully disposing an owned spell. The owning Spellbook decides the disposal, every contract that holds the version drops it, then the Spellbook disposes it: it removes the spell from every resolution surface, destroys its index if it was the sole member, and tears the spell object down; when the index was destroyed, its index-link borrowers drop their subscription to it.
Contract:
CONTRACTS FIRST, THEN THE DISPOSAL (the owner's order, 2026-10-19): after the Spellbook's locked decision and before it disposes anything, every contract of the Book's root conduit that holds the version - an index link's member Detail or a version grant - drops it, with the borrower's entry, active or parked, and its borrowed id (ConduitWard._emit_spell_disposed). No borrower is left holding a version its lender disposed, nor a cleaned Spell. (cleanup_releases_contracts_2026_10_19, 0.2.8261)
The contracts live on the Book's root conduit, so a call through a lesser conduit of its lineage reaches them too; the Spellbook's own cleanup_spell comes here once the Book has conjured.
The Spellbook decides, under its own lock, whether the disposal destroys the spell's index, and reports the destroyed index's id; the destroy is emitted to index-link borrowers exactly then, after the disposal and with no member id, the version having left every contract already (an index is destroyed only when the spell was its sole member). Nothing about the spell or its index is read here before that decision.
A refused call (see Raises) changes no contract.
Not admitted through a transaction (no cleanup strategy exists), so a link or grant of the same version that lands between the release and the disposal is not ordered against it.
- Parameters:
spell -- The owned spell to dispose.
- Raises:
RuntimeError -- If the Conduit is cleaned or has no owning Spellbook.
RuntimeError -- If the spell has already been disposed, is being disposed by another call, is not owned by the owning Spellbook, or is the active member of a multi-member index (raised by Spellbook._dispose_spell before any contract changes).
RuntimeError -- From the release, if a borrower's Book holds no entry for the version under a lender-side Detail; nothing is disposed, and a retry repeats the release.
- Threading:
Takes no lock of its own. The Spellbook takes the Book lock and the spell's own lock (never nested) and runs the release with neither held; the release and the destroy emission walk the root ward's contracts under the ward lock (ward -> contract -> borrower Book), so a concurrent link or sever of the root waits for them. (cross_object_lock_gaps, 0.2.8231) Of two calls for one spell that overlap, the Spellbook lets the first dispose it and refuses the second, so each contract drops the version once and the destroy is emitted once. (lock_residuals, 0.2.8232)
- Returns:
None.
- sever_link(target_conduit: Conduit) bool[source]ο
Public API
Sever the link and the corresponding spell contracts between this Conduit and its target Conduit.
This method validates the link's existence, ensures it can be severed according to policy, and removes the link and all contracted spells. This is intended for public use to dissolve a relationship.
On success, the following hook will be fired on this Conduit (if configured):
- "on_conduit_post_unlink(self, target_conduit)"
- Parameters:
target_conduit (Conduit) -- The target Conduit whose link to sever.
- Returns:
True if the link was successfully severed.
- Return type:
bool
- Raises:
RuntimeError -- If the Conduit is cleaned.
RuntimeError -- If dynamic environment is not enabled.
- get_links() list[Conduit][source]ο
Public API
Returns a list of all active peer links associated with this conduit.
This list excludes links to lesser (child) conduits.
- Returns:
A list of the linked conduit instances.
- Return type:
list
- Raises:
RuntimeError -- If the Conduit is cleaned.
RuntimeError -- If dynamic environment is not enabled.
- get_lesser_conduit(conduit_id: str) Conduit | None[source]ο
Internal
Returns a specific lesser conduit (child) linked to this conduit by its ID.
- Parameters:
conduit_id (str) -- The ID of the lesser conduit to retrieve.
- Returns:
The linked lesser conduit if found, otherwise None.
- Return type:
Optional["Conduit"]
- Raises:
RuntimeError -- If the Conduit is cleaned.
- get_initiated_conduit(conduit_id: str) Conduit | None[source]ο
Public API
Retrieves the conduit that this conduit has initiated a contract toward.
This method uses the internal index to resolve an outbound connection, where this conduit was the initiator of the contract.
- Parameters:
conduit_id (str) -- The ID of the target conduit this conduit linked to.
- Returns:
The target conduit if the link exists, otherwise None.
- Return type:
Optional[Conduit]
- Raises:
RuntimeError -- If the Conduit is cleaned.
- get_provider_conduit(conduit_id: str) Conduit | None[source]ο
Public API
Retrieves the conduit that initiated a contract to this conduit.
This method uses the internal index to resolve an inbound connection, where another conduit linked to this one as the provider.
- Parameters:
conduit_id (str) -- The ID of the source conduit that linked to this one.
- Returns:
The source conduit if the link exists, otherwise None.
- Return type:
Optional[Conduit]
- Raises:
RuntimeError -- If the Conduit is cleaned.
- get_initiated_conduits() list[Conduit][source]ο
Public API
Returns a list of all conduits that this conduit has initiated contracts toward (outbound links).
This is useful for understanding the dependencies and relationships initiated by this conduit.
- Returns:
A list of conduits this conduit linked to.
- Return type:
list[Conduit]
- Raises:
RuntimeError -- If the Conduit is cleaned.
- get_provider_conduits() list[Conduit][source]ο
Public API
Returns a list of all conduits that have initiated contracts to this conduit (inbound links).
These are the conduits that depend on this one for contracted spells.
- Returns:
A list of conduits that have linked to this conduit as the provider.
- Return type:
list[Conduit]
- Raises:
RuntimeError -- If the Conduit is cleaned.
- cleanup_lesser_conduits() None[source]ο
Public API
Cleans up all lesser conduits (children) linked to this conduit.
This prevents further operations on lesser conduits and is typically used when the parent is cleaning or undergoing a major state change (e.g., upgrade).
- Raises:
RuntimeError -- If the Conduit is cleaned.
- Returns:
None.
- get_resolution_state() ConduitResolutionState | None[source]ο
Public API
Return the per-conduit resolution state for this conduit.
- Purpose:
Provide access to conduit-scoped Phase 5-7 validity and diagnostics after linking/contracting without running validation.
Contract:
Does not run validation or mutate any state.
For lesser conduits, uses the root conduit id.
Returns None when no resolution state has been recorded yet.
- Returns:
The resolution state for this conduit (or its root), if present.
- Return type:
ConduitResolutionState | None
- Raises:
RuntimeError -- If the conduit is cleaned or the root conduit is unavailable.
RuntimeError -- If the Spellbook is not available on this conduit.
- Threading:
Uses the conduit lock to resolve lineage/root identity. The returned state is owned by SpellSystemStates and provides its own locking.
- validate_resolution(*, refresh_structural: bool = True) ConduitResolutionState | None[source]ο
Public API
Run structural and conduit-scoped resolution validation, then return the state.
- Purpose:
Provide an explicit preflight validation hook after linking or contracting spells so callers (including AI users) can check readiness before performing work.
Contract:
When refresh_structural is True, runs structural phases (1-4) first.
Always runs resolution phases (5-7) for this conduit scope.
Returns the conduit-scoped resolution state after validation.
- Parameters:
refresh_structural -- Whether to re-run structural validation (phases 1-4) before conduit-scoped phases. Defaults to True.
- Returns:
The resolution state for this conduit (or its root), if present.
- Return type:
ConduitResolutionState | None
- Raises:
RuntimeError -- If the conduit is cleaned or the root conduit is unavailable.
RuntimeError -- If the Spellbook or SpellSystemStates are unavailable.
SpellbookValidationError -- Propagated if structural or resolution validation fails.
- Threading:
Resolves conduit identity under the conduit lock but executes phase pipelines outside of it to avoid long-held locks.
- add_spell_to_contract(*, spell: Spell | None = None, spell_id: str | None = None, conduit: Conduit | None = None, conduit_id: str | None = None, permissions: str = 'create', aetheric_frame: str = 'default', reason: DetailReason = DetailReason.manual, root_spell_id: str | None = None, link_dependencies: bool = False) bool | None[source]ο
Public API
Establishes a single spell contract between this conduit and another target conduit.
This allows one conduit to borrow or grant a specific spell, identified either by object or ID, to/from a peer conduit. The contract defines the permissions under which the spell can be used.
You must provide either a spell object or a spell_id. The target conduit must be specified either directly or resolved via its ID and aetheric frame. Contract mutations require an active link transaction that includes both conduits.
- Parameters:
spell (Spell, optional) -- The spell object to contract.
spell_id (str, optional) -- The unique ID of the spell to contract.
conduit (Conduit, optional) -- The target conduit to contract with.
conduit_id (str, optional) -- The str of the target conduit (used if conduit is not provided).
permissions (str) -- The permission level granted for this spell (default is "create").
aetheric_frame (str) -- Optional frame override used to locate the target conduit.
reason (DetailReason) -- The reason for the contract (default is DetailReason.manual).
link_dependencies (bool) -- Whether to link dependencies (default is False).
root_spell_id (str, optional) -- The root spell id for this contract (default is None).
- Returns:
True if the contract was created, False otherwise. None if an internal error occurs.
- Return type:
bool | None
- Raises:
RuntimeError -- If the Conduit fails contract qualification checks (cleaned, not normal, not dynamic).
RuntimeError -- If no active link transaction is present for this contract mutation.
- add_index_to_contract(*, index: Any, conduit: Conduit | None = None, conduit_id: str | None = None, permissions: str = 'create', aetheric_frame: str = 'default', reason: DetailReason = DetailReason.manual) bool[source]ο
Public API
Link a whole SpellIndex into a contract with a target conduit, so the borrower follows the index's active (selected) member rather than a captured version, admitted as an add_spell_or_index_to_contract change-control transaction. The index counterpart of add_spell_to_contract.
Contract:
Reuses an active link/cluster/transfer window when one is already open (so the cluster and transfer flows are unaffected); otherwise self-admits a dedicated add_spell_or_index_to_contract transaction that seals the borrower + provider conduits (and their wards) EXCLUSIVE for the duration.
The index link itself runs inside the held window via the Conduit-owned _conduit_ward._add_index_to_contract seam.
- Parameters:
index -- The owned SpellIndex to share.
conduit_id (conduit /) -- The target (owner/provider) conduit.
permissions -- Permission to grant (default "create").
aetheric_frame -- Frame override used to locate the target conduit.
reason -- Why this index contract exists.
- Returns:
True if the index link was created.
- Return type:
bool
- Raises:
RuntimeError -- If contract qualification fails (cleaned / not normal / not dynamic), or -- when reusing an existing window -- no active link transaction is present.
- Threading:
The transaction embargo is acquired before the ward lock, so a concurrent bind/link cannot deadlock the add.
- remove_index_from_contract(*, index_id: str, conduit: Conduit | None = None, conduit_id: str | None = None, aetheric_frame: str = 'default') None[source]ο
Public API
Release a whole SpellIndex-link from the contract with a target conduit and untrack the index on the borrower, admitted as a remove_spell_or_index_from_contract change-control transaction. The reverse of add_index_to_contract.
Contract:
Reuses an active link/cluster/transfer window when one is already open (so the cluster and transfer flows are unaffected); otherwise self-admits a dedicated remove_spell_or_index_from_contract transaction that seals the borrower + provider conduits (and their wards) EXCLUSIVE for the duration.
The untrack itself runs inside the held window via the Conduit-owned _conduit_ward._remove_index_from_contract seam.
- Parameters:
index_id -- Stable id of the linked index to release.
conduit_id (conduit /) -- The target (owner/provider) conduit.
aetheric_frame -- Frame override used to locate the target conduit.
- Raises:
RuntimeError -- If contract qualification fails (cleaned / not normal / not dynamic), or -- when reusing an existing window -- no active link transaction is present.
- Threading:
The transaction embargo is acquired before the ward lock, matching the add-side ordering, so a concurrent bind/link cannot deadlock the removal.
- Returns:
None.
- add_spells_to_contract(spell_ids: list[str], conduit: Conduit | None = None, conduit_id: str | None = None, permissions: str = 'create', aetheric_frame: str = 'default', reason: DetailReason = DetailReason.manual, link_dependencies: bool = False) Dict[str, bool][source]ο
Public API
Establishes multiple spell contracts with another conduit in a single operation.
Allows you to bulk-grant or bulk-borrow spells by specifying a list of spell IDs. Each spell will be contracted using the same permission level.
- Parameters:
spell_ids (list[str]) -- List of spell IDs to contract.
conduit (Conduit, optional) -- The target conduit to contract with.
conduit_id (str, optional) -- The id of the target conduit (used if conduit is not provided).
permissions (str) -- The permission level granted for all spells (default is "create").
aetheric_frame (str) -- Optional frame override used to locate the target conduit.
reason (DetailReason) -- The reason for the contract (default is DetailReason.manual).
link_dependencies (bool) -- Whether to link dependencies (default is False).
- Returns:
Dictionary of spell_id -> success boolean for each attempted contract.
- Return type:
Dict
- Raises:
RuntimeError -- If the Conduit fails contract qualification checks (cleaned, not normal, not dynamic).
RuntimeError -- If no active link transaction is present for this contract mutation.
- remove_spell_from_contract(*, spell: Spell | None = None, spell_id: str | None = None, conduit: Conduit | None = None, conduit_id: str | None = None, root_spell_id: str | None = None, aetheric_frame: str = 'default') bool | None[source]ο
Public API
Removes a single spell contract between this conduit and another.
Either the spell or spell_id can be provided to specify the contract to dissolve. Once removed, the spell is no longer accessible across the link.
- Parameters:
spell (Spell, optional) -- The spell object to remove.
spell_id (str, optional) -- The unique ID of the spell to remove.
conduit (Conduit, optional) -- The target conduit involved in the contract.
conduit_id (str, optional) -- id of the target conduit (used if conduit not provided).
aetheric_frame (str) -- Optional frame override to resolve the target conduit.
- Returns:
True if the spell was successfully removed from the contract, False otherwise. None if an internal error occurs.
- Return type:
bool | None
- Raises:
RuntimeError -- If the Conduit fails contract qualification checks (cleaned, not normal, not dynamic).
RuntimeError -- If no active link transaction is present for this contract mutation.
- remove_spells_from_contract(*, spell_ids: list[str] | None = None, conduit: Conduit | None = None, conduit_id: str | None = None, root_spell_id: str | None = None, aetheric_frame: str = 'default') Dict[str, bool][source]ο
Public API
Removes multiple spells from an existing contract with a target conduit.
Useful for bulk cleanup or revocation when retiring behaviors or permissions.
- Parameters:
spell_ids (list[str], optional) -- List of spell IDs to remove.
conduit (Conduit, optional) -- Target conduit object.
conduit_id (str, optional) -- str of target conduit (used if conduit is not provided).
aetheric_frame (str) -- Optional frame override.
root_spell_id (str, optional) -- str of root spell ID (used if conduit is not provided).
- Returns:
Dictionary of spell_id -> success boolean for each removal attempt.
- Return type:
dict
- Raises:
RuntimeError -- If the Conduit fails contract qualification checks (cleaned, not normal, not dynamic).
RuntimeError -- If no active link transaction is present for this contract mutation.
- remove_root_from_contracts(*, root_spell_id: str, conduit: Conduit | None = None, conduit_id: str | None = None, aetheric_frame: str = 'default') dict[source]ο
Public API
Removes a root spell_id (and any dependency Details attributed to it) from one contract or all contracts. Orphaned Details trigger contracted spell removal; empty contracts are severed.
Contract mutations require an active link transaction that includes the borrower and the peer conduits involved in the contract cleanup.
Contract:
REQUIRES AN ACTIVE LINK TRANSACTION; it is not a bare mutation. The transaction requirement is checked before anything is removed.
Qualifies contracts first, so the removal operates on a settled view rather than a stale one.
Removes the ROOT spell from contracts and returns a report of what was actually removed - read it rather than assuming a full sweep.
- Threading:
Serialized by the surrounding link transaction.
- Lifecycle / Cleanup:
Guarded via the contract-qualification path.
- Raises:
RuntimeError -- If no suitable link transaction is active.
- Returns:
- Per-peer removal outcome keyed by contract, describing what was
untracked on each side.
- Return type:
dict
- Parameters:
root_spell_id -- The root spell whose contracted details should be untracked across every peer contract this conduit participates in.
- add_spell_to_contract_with_dependencies(*, spell: Spell | None = None, spell_id: str | None = None, conduit: Conduit | None = None, conduit_id: str | None = None, permissions: str = 'create', aetheric_frame: str = 'default') bool | None[source]ο
Public API helper
Adds a spell to a contract and automatically links its dependencies (recursively) using the same permission level (downgraded to read when needed).
Contract:
CONVENIENCE WRAPPER over add_spell_to_contract(...) that stamps DetailReason.root, marking the spell as a deliberately contracted ROOT rather than something pulled in as a dependency.
It adds no logic of its own; every gate, transaction requirement and raise belongs to the wrapped call.
The reason stamp is what later lets contract reports tell roots apart from dependency-driven entries.
- Threading:
Inherited from add_spell_to_contract(...).
- Lifecycle / Cleanup:
Inherited from add_spell_to_contract(...).
- Raises:
RuntimeError -- Propagated from add_spell_to_contract(...).
- Returns:
- True when the spell and its dependency closure were added,
False when refused, None when there was no contract to act on.
- Return type:
Optional[bool]
- Parameters:
spell -- The spell (one version) to grant across the existing contract.
peer_conduit -- The borrowing peer that should gain access.
- get_all_spells_in_contracts(validate: bool = True) dict[str, list[Tuple[str, Spell]]] | None[source]ο
Public API
Retrieves all active spells that this conduit has access to through its contracts (i.e., borrowed spells).
Walks all current spell contracts and collects the spell IDs and objects that are currently borrowed from other conduits. Optionally validates contracts before collecting data.
- Parameters:
validate (bool) -- If True, performs contract consistency validation before returning data.
- Returns:
Dictionary mapping peer conduit ids to lists of (spell_id, Spell) tuples, or None if no contracts exist.
- Return type:
Optional[dict[str, list[Tuple[str, Spell]]]]
- Raises:
RuntimeError -- If the Conduit fails contract qualification checks (cleaned, not normal, not dynamic).
TypeError -- If validate is not a boolean.
- get_spell_in_contracts(spell_id: str) tuple[str, Spell] | None[source]ο
Public API
Searches all known contracts to find the origin of a specific contracted spell.
Looks for a specific spell by ID and returns the str of the conduit it's contracted from along with the spell object, if found.
- Parameters:
spell_id (str) -- The unique ID of the spell.
- Returns:
Tuple of (conduit_id, spell) if found, otherwise None.
- Return type:
Optional[tuple[str, Spell]]
- Raises:
RuntimeError -- If the Conduit fails contract qualification checks (cleaned, not normal, not dynamic).
TypeError -- If spell_id is not a string.
- get_spells_in_contract_by_conduit(conduit_id: str) dict[str, list[tuple[str, Spell]]] | None[source]ο
Public API
Retrieves all spell contracts associated with a specific peer conduit, identified by id.
Returns a detailed list of all spells that this conduit currently accesses or has granted through its relationship with the specified peer.
- Parameters:
conduit_id (str) -- id of the target peer conduit.
- Returns:
Dictionary of spell_id -> (spell_id, Spell) tuples or None if not found. If a contract exists but has no spells, inbound/outbound lists are empty.
- Return type:
dict[str, list[tuple[str, Spell]]] | None
- Raises:
RuntimeError -- If the Conduit fails contract qualification checks (cleaned, not normal, not dynamic).
TypeError -- If conduit_id is not a str.
- get_spells_in_contract_by_conduit_name(conduit_name: str) dict[str, list[tuple[str, Spell]]] | None[source]ο
Public API
Retrieves all spell contracts associated with a peer conduit identified by name.
Performs resolution using a human-readable name instead of str.
- Parameters:
conduit_name (str) -- Name of the peer conduit.
- Returns:
Dictionary of spell_id -> (spell_id, Spell) tuples or None if not found.
- Return type:
dict[str, list[tuple[str, Spell]]] | None
- Raises:
RuntimeError -- If the Conduit fails contract qualification checks (cleaned, not normal, not dynamic).
TypeError -- If conduit_name is not a string.
- get_contracted_conduits() list[Tuple[str, Conduit]] | None[source]ο
Public API
Lists all conduits that have an active spell contract with this conduit.
Each returned conduit represents a peer in the current dynamic spell network.
- Returns:
List of (conduit_id, Conduit) tuples, or None if no contracts exist.
- Return type:
list[Tuple[str, Conduit]] | None
- Raises:
RuntimeError -- If the Conduit fails contract qualification checks (cleaned, not normal, not dynamic).
- snapshot_state() Dict[str, Any][source]ο
Public API
Build a read-only snapshot of Conduit state.
- Purpose:
Provide a stable view of conduit metadata and Spellbook registries for diagnostics while transactions may be in-flight.
Contract:
Returns detached copies of metadata and Spellbook snapshot data.
Includes a snapshot id for observability.
- Returns:
Snapshot payload with conduit metadata and Spellbook snapshot.
- Return type:
Dict[str, Any]
- Raises:
RuntimeError -- If the Conduit has been cleaned.
- Threading:
Acquires the Conduit lock while copying local metadata, then snapshots the Spellbook outside the lock.
- validate_contracts_and_define() dict[str, bool][source]ο
Public API
Validates all known contracts attached to this conduit and confirms mutual agreement and consistency.
This performs a deep validation pass, ensuring both sides list the same spells, permissions are symmetrical, and all referenced spells are valid.
- Returns:
Dictionary mapping contract ids to validation results:
True: Contract is valid and consistent
False: Contract is malformed or inconsistent
- Return type:
dict[str, bool]
- Raises:
RuntimeError -- If the Conduit fails contract qualification checks (cleaned, not normal, not dynamic).
- validate_received_contracts() bool[source]ο
Public API
Performs a high-level validation check across all contracts involving this conduit.
Aggregates the results of _validate_contracts_and_define to determine whether every connected contract is structurally valid and symmetrical.
- Returns:
True if all active contracts pass validation, False otherwise.
- Return type:
bool
- Raises:
RuntimeError -- If the Conduit fails contract qualification checks (cleaned, not normal, not dynamic).