On this page
- SpellbookConfiguration
SpellbookConfigurationSpellbookConfiguration.cleanup()SpellbookConfiguration.set_property()SpellbookConfiguration.clear_properties()SpellbookConfiguration.freeze()SpellbookConfiguration.validate()SpellbookConfiguration.validate_enums()SpellbookConfiguration.get_property()SpellbookConfiguration.has_property()SpellbookConfiguration.load_default_dictionary()SpellbookConfiguration.load_recorded_dictionary()SpellbookConfiguration.add_hook()SpellbookConfiguration.add_hooks()SpellbookConfiguration.get_conduit_hooks()SpellbookConfiguration.get_meld_hooks()SpellbookConfiguration.get_hooks()SpellbookConfiguration.with_phase_scheduler_workers()SpellbookConfiguration.with_phase_scheduler_barrier_timeout()SpellbookConfiguration.with_hook()SpellbookConfiguration.with_hooks()SpellbookConfiguration.with_defaults()SpellbookConfiguration.with_disposal()SpellbookConfiguration.with_enforce_priority_disposal_methods()SpellbookConfiguration.with_disposal_method_names()SpellbookConfiguration.add_disposal_methods()SpellbookConfiguration.finalize()SpellbookConfiguration.build()
SpellbookConfigurationο
Use md.SpellbookConfiguration from the public package namespace.
- class SpellbookConfiguration(aether_frame: str = 'default')[source]ο
Mutable build-time configuration surface for one spellbook/runtime context.
SpellbookConfiguration is the central staging object for one Spellbook's rich local runtime behaviour. It owns the typed property map, idempotent keys, and the per-spellbook system hook registry that later runtime systems consume.
It governs:
local Spellbook/runtime behaviour
disposal and phase-scheduler tuning
hook registration for Meld / Conduit / Link / Contract events
Contract:
Properties are mutable only until the configuration is frozen.
Idempotent keys may be set once and then become immutable even before freeze.
Validation is explicit and freeze/finalize enforce it.
Thread-safe operations are serialized with the instance RLock.
- Registration:
MELDER KERNEL - guarded. Created or adopted during Spellbook.__init__; users configure it directly, which is its whole purpose.
- Subsystem Context:
The rich per-spellbook configuration, distinct from the NARROW AethericFrameConfiguration derived from it at conjure. It owns the typed property map, idempotent keys, and the system hook registry for Meld / Conduit / Link / Contract events.
- System Context:
IDEMPOTENT KEYS are the unusual and important mechanism here: they may be set ONCE and then become immutable EVEN BEFORE FREEZE. That exists because some properties are adopted from a frame-shared configuration or established at first bind, and letting them be rewritten later would silently change the contract that earlier binds already committed to. Freeze is the second gate: configuration must be frozen before a Conduit can be created, so the conjure pipeline plans against values that cannot move underneath it. The crystallizer enforces the same discipline from the record side - a dynamic conjure over binds that ran while the configuration was still mutable is REFUSED, because a recorded world must never be born config-incoherent. Hooks living here rather than on the Spellbook is what makes them adoptable: a frame-shared configuration carries one hook registry for every book that adopts it.
AGENT_ACCESS: public
- AGENT_PURPOSE:
access: public. Rich per-book configuration: typed properties, idempotent keys, and the Meld/Conduit/Link/Contract hook registry. Must be frozen before conjure. Idempotent keys lock after first set, even before freeze.
- cleanup() None[source]ο
Finalize the configuration and drop all owned registries.
This method sets both the cleaned and frozen flags.
Contract:
Idempotent and lock-guarded.
Clears property/type maps and hook registries.
Prevents any future mutation or validation calls through check_cleaned().
- Raises:
RuntimeError -- If the configuration is already cleaned.
- Returns:
None.
- set_property(key: str, value: Any) None[source]ο
Defines or overwrites a property in the configuration.
Idempotent properties (e.g., 'system_state') can only be set once before the configuration is cleaned.
Non-idempotent properties can be freely modified before the configuration is frozen.
- Parameters:
key (str) -- The name of the property to set.
value (Any) -- The value of the property.
- Raises:
RuntimeError -- If the configuration is cleaned or frozen.
RuntimeError -- If attempting to modify an idempotent property that is already set.
TypeError -- If key is not a string.
ValueError -- If local value validation fails.
- Returns:
None.
- clear_properties() None[source]ο
Reset authored properties to the initial build-time state.
The disposal-priority flag returns to False; all other properties are removed. The configuration remains available for reassembly before freeze.
- Raises:
RuntimeError -- If the configuration is cleaned or frozen.
- Returns:
None.
- freeze(origin_spellbook_id: str | None = None, origin_frame_name: str | None = None, origin_dynamic: bool | None = None) None[source]ο
Freezes the configuration property system.
Once frozen, no properties, including non-idempotent ones, can be modified. Validation is performed automatically upon freezing.
Contract:
Freezing is this configuration's true activation, so it is the emission factor for the spellbook twin: when origin identity is supplied, the world is dynamic, and the crystallizer records, the twin spawns into the active persistence profile.
Standalone freezes (user finalize()/build() before any Spellbook adoption) carry no origin identity and emit nothing; the owning spellbook's conjure-time freeze supplies identity.
- Parameters:
origin_spellbook_id -- Owning spellbook identity, supplied by the spellbook's conjure-time freeze path; None for standalone freezes.
origin_frame_name -- Owning frame name (the twin's parent edge).
origin_dynamic -- Conjure-time dynamic posture; the twin emits only when True (the recorded lane).
- Raises:
RuntimeError -- If the configuration is cleaned.
ValueError -- If configuration validation fails prior to freezing (e.g., missing required properties).
- Returns:
None.
- validate() bool[source]ο
Validates that all configuration properties are present, correctly typed, and semantically valid.
The validation pipeline is intentionally decomposed into small, focused helper methods to avoid an overly long and unmaintainable validate() method.
Contract:
Checks the configuration's own coherence. It does not consult any spellbook, so passing here does not guarantee a given spellbook will accept the configuration.
Raises on violation rather than returning False.
- Threading:
State transitions are applied under the configuration lock.
- Lifecycle / Cleanup:
Guarded by check_cleaned().
- Raises:
RuntimeError -- If the configuration has been cleaned.
- Returns:
- True when every required property is present and coherent. Raises
rather than returning False for a missing required property.
- Return type:
bool
- validate_enums() bool[source]ο
Local rich configuration no longer owns enum-backed frame posture properties, so enum validation is a no-op.
- Returns:
True if all enum values are valid.
- Return type:
bool
- Raises:
RuntimeError -- If the configuration is cleaned.
ValueError -- If a known enum property is set to an invalid type.
- get_property(key: str) Any[source]ο
Return one configuration property value.
- Parameters:
key (str) -- The name of the property.
- Returns:
The stored value (str, int, bool, Enum, etc.).
- Return type:
Any
- Raises:
RuntimeError -- If the configuration is cleaned.
KeyError -- If the property does not exist in the configuration.
Contract:
Returns the stored live value for the key.
Raises instead of silently defaulting when the key is missing.
- has_property(key: str) bool[source]ο
Return whether a configuration property is currently defined.
- Parameters:
key (str) -- The property name to check.
- Returns:
True if the property exists, False otherwise.
- Return type:
bool
- Raises:
RuntimeError -- If the configuration is cleaned.
- load_default_dictionary() None[source]ο
Load the standard default property set.
This method sets sensible defaults for local rich-config properties.
Contract:
Populates only missing local rich-config properties; existing explicit values are preserved.
- Raises:
RuntimeError -- If the configuration is cleaned.
- Returns:
None.
- load_recorded_dictionary(recorded_properties: Dict[str, Any]) Dict[str, List[str]][source]ο
Reload lane: apply one RECORDED property payload as configuration truth.
- Purpose:
The restore/reload counterpart to load_default_dictionary. A sealed world must rebuild from its recorded values - never from present-day defaults, which drift - so this verb applies the recorded payload first and backfills ONLY required keys the record does not carry, reporting every deviation to the caller.
Contract:
Recorded values win: each recorded key routes through set_property for registration/lifecycle checks; type checking occurs during the final validation/freeze.
A recorded key the property system refuses (unknown key or lifecycle/write-once violation) is skipped and returned under "rejected" as "key: reason"; nothing is silently coerced. The per-key exception capture is documented best-effort collection, not error swallowing - every refusal is surfaced to the caller. Invalid registered value types fail at the final validation.
Required keys absent from the record backfill through load_default_dictionary (populate-missing-only semantics) and each backfilled key is returned under "backfilled"; nothing backfills silently.
An omitted disposal-priority flag still holding its eager False default is also reported as backfilled. An existing non-default True is preserved when the record has no replacement.
LOADS AND FREEZES in one motion: a reloaded configuration is sealed truth, so the verb validates and freezes internally before returning - callers never finalize a reload. The standalone freeze carries no origin identity (no twin emission); the owning spellbook's conjure-time freeze re-enters with identity and emits.
- Parameters:
recorded_properties -- Property name -> recorded value mapping (one sealed, JSON-safe configuration_payload - the cached-item shape).
- Returns:
- {"rejected": ["key: reason", ...] for refused recorded
values, "backfilled": [key, ...] for schema-default fills}.
- Return type:
Dict[str, List[str]]
- Raises:
RuntimeError -- If the configuration is cleaned.
ValueError -- If the reloaded property set fails validation at the internal freeze.
- add_hook(spellbook_id: str, hook_name: str, hook: Callable[[...], Any]) None[source]ο
Register a single system hook under this configuration for a specific Spellbook.
The registry is keyed as:
_hooks[spellbook_id][hook_name] -> list[callables]
Covered hook categories:
Meld pipeline hooks:
- "on_meld_pre_resolve" - "on_meld_post_resolve"
Conduit lifecycle hooks:
- "on_conduit_pre_created" - "on_conduit_post_created" - "on_conduit_activated" - "on_conduit_cleanup_start" - "on_conduit_cleanup_complete"
Linking hooks:
- "on_conduit_post_link" - "on_conduit_post_unlink"
Contract hooks:
- "on_contract_created" - "on_contract_removed"
- Parameters:
spellbook_id (str) -- The ID of the Spellbook these hooks belong to. This allows dynamic environments to register hooks per-Spellbook and later pull the appropriate hook sets when instantiating Conduits.
hook_name (str) -- The canonical hook name to register. Must be one of: attr:_ALLOWED_HOOKS.
hook (Callable[..., Any]) -- A callable to be invoked when the corresponding hook event fires.
- Raises:
RuntimeError -- If the configuration is cleaned or frozen.
ValueError -- If hook_name is unknown.
TypeError -- If hook is not callable.
- Returns:
None.
- add_hooks(spellbook_id: str, **hooks: Any) None[source]ο
Register multiple system hooks for a specific Spellbook in one call.
Each keyword argument maps a hook name to either:
A single callable, or
An iterable of callables.
The internal registry shape is:
_hooks[spellbook_id][hook_name] -> list[callables]
Example
cfg.add_hooks("spellbook-123", on_meld_pre_resolve=trace_meld_enter, on_conduit_cleanup_complete=[cleanup_fn_1, cleanup_fn_2], on_contract_created=contract_observer, )
- Parameters:
spellbook_id (str) -- The ID of the Spellbook these hooks belong to.
**hooks -- Mapping of hook name -> callable or iterable[callable].
- Raises:
RuntimeError -- If the configuration is cleaned or frozen.
ValueError -- If any hook name is unknown.
TypeError -- If any value is not a callable or an iterable of callables.
- Returns:
None.
- get_conduit_hooks(spellbook_id: str) Dict[str, list[Callable[[...], Any]]][source]ο
Retrieve the live conduit hook map for a specific Spellbook.
This returns the internal conduit hook map for spellbook_id.
Shape:
{ hook_name: [callables...] }
- Parameters:
spellbook_id (str) -- The ID of the Spellbook whose conduit hooks should be retrieved.
- Returns:
Mapping of hook name -> list of callables currently registered for that Spellbook. Returns an empty dict if no conduit hooks exist.
- Return type:
Dict[str, list[Callable[..., Any]]]
- Raises:
RuntimeError -- If the configuration is cleaned.
- get_meld_hooks(spellbook_id: str) Dict[str, list[Callable[[...], Any]]][source]ο
Retrieve the live meld hook map for a specific Spellbook.
This returns the internal meld hook map for spellbook_id.
- Parameters:
spellbook_id (str) -- The ID of the Spellbook whose meld hooks should be retrieved.
- Returns:
Mapping of hook name -> list of callables currently registered for that Spellbook. Returns an empty dict if no meld hooks exist.
- Return type:
Dict[str, list[Callable[..., Any]]]
- Raises:
RuntimeError -- If the configuration is cleaned.
- get_hooks(spellbook_id: str) Dict[str, list[Callable[[...], Any]]][source]ο
Retrieve a merged detached hook map for compatibility callers.
Contract:
KEYED BY SPELLBOOK ID. Hooks in this configuration are per-spellbook, not global, so this returns only the hooks registered for the id you pass.
Returns a DETACHED MERGED VIEW of the conduit and meld hook maps - a new dict of new lists. Mutating the result does NOT change registered hooks; use with_hook / with_hooks for that.
An id with no registered hooks yields an empty map rather than raising.
NOTE: the Args block below documents hook_name, which this method does not take. The single parameter is spellbook_id.
- Threading:
State transitions are applied under the configuration lock.
- Lifecycle / Cleanup:
Guarded by check_cleaned().
- Raises:
RuntimeError -- If the configuration has been cleaned.
- Returns:
Detached merged view of conduit and meld hooks.
- Return type:
Dict[str, list[Callable[..., Any]]]
- Parameters:
hook_name -- Registered hook name to look up, for example a Meld or Conduit lifecycle event.
- with_phase_scheduler_workers(workers: int) SpellbookConfiguration[source]ο
Set the number of worker threads used by the Resolution Phase Scheduler. Must be >= 1.
- Parameters:
workers (int) -- Number of worker threads.
- Returns:
This same configuration instance (for chaining).
- Return type:
Contract:
Validates the worker count before writing it.
Mutates the live configuration and returns self.
- with_phase_scheduler_barrier_timeout(timeout_milliseconds: int) SpellbookConfiguration[source]ο
Set the barrier timeout in milliseconds used by the Resolution Phase Scheduler. Must be >= 0.
- Parameters:
timeout_milliseconds (int) -- Barrier timeout in milliseconds.
- Returns:
This same configuration instance (for chaining).
- Return type:
Contract:
Rejects zero and excessively large values up front.
Mutates the live configuration and returns self.
- with_hook(spellbook_id: str, hook_name: str, hook: Callable[[...], Any]) SpellbookConfiguration[source]ο
Fluent
Register a single system hook for a specific Spellbook and return "self".
This is a fluent wrapper over: meth:add_hook, supporting all valid hook names defined in: attr:_ALLOWED_HOOKS.
Example
(SpellbookConfiguration() .with_defaults() .with_hook("spellbook-123", "on_meld_pre_resolve", trace_meld_enter) .with_hook("spellbook-123", "on_conduit_cleanup_complete", cleanup_fn) .finalize())
Contract:
REGISTERS ONE HOOK FOR ONE SPELLBOOK ID - the first parameter is the spellbook id, not the hook name. Hooks are per-spellbook, so the same configuration can carry different hooks for different books.
Fluent wrapper over add_hook; it delegates and returns self, adding no validation of its own. Hook names are validated against the allowed-hook set by the underlying call.
ADDITIVE: registering again appends rather than replacing, so calling it twice with the same callable registers it twice.
Refused once frozen.
- Threading:
State transitions are applied under the configuration lock.
- Lifecycle / Cleanup:
Guarded by check_cleaned().
- Raises:
RuntimeError -- If the configuration has been cleaned.
- Returns:
This configuration, for fluent chaining.
- Return type:
- Parameters:
hook_name -- The lifecycle event to attach to.
hook -- The callable to invoke. Recorded by NAME only - the crystallizer cannot restore the function itself.
- with_hooks(spellbook_id: str, **hooks: Any) SpellbookConfiguration[source]ο
Fluent
Register multiple system hooks for a specific Spellbook in one call and return "self".
Each keyword argument maps a hook name to either:
A single callable, or
An iterable of callables.
Example
(SpellbookConfiguration() .with_defaults() .with_hooks("spellbook-123", on_meld_pre_resolve=trace_meld_enter, on_conduit_pre_created=log_conduit_construction, on_contract_created=[observer_1, observer_2], ) .finalize())
Contract:
REGISTERS MANY HOOKS FOR ONE SPELLBOOK ID in a single call; the first parameter is the spellbook id and each keyword is a hook name.
Each keyword value may be a SINGLE CALLABLE or an ITERABLE OF CALLABLES; both shapes are accepted and flattened into the same registration.
ADDITIVE, like with_hook - it appends to whatever is already registered rather than replacing it.
Refused once frozen.
- Threading:
State transitions are applied under the configuration lock.
- Lifecycle / Cleanup:
Guarded by check_cleaned().
- Raises:
RuntimeError -- If the configuration has been cleaned.
- Returns:
This configuration, for fluent chaining.
- Return type:
- Parameters:
hook_name -- The lifecycle event to attach to.
hooks -- One or more callables to invoke, in registration order.
- with_defaults() SpellbookConfiguration[source]ο
Fluent
Load Melderβs standard defaults into this configuration and return self so you can keep chaining.
Behaviour:
Sets local rich-config defaults: disposal=False, disposal_method_names=[], enforce_priority_disposal_methods=False.
Respects idempotency and immutability rules (raises if frozen or cleaned).
Contract:
MUTATES THIS OBJECT and returns self; not a copying builder.
SEEDS ONLY WHAT IS MISSING. It delegates to load_default_dictionary(), which writes a default ONLY when the key is absent (if key not in self._properties). Values you set earlier are PRESERVED, not replaced.
Therefore it is NOT a reset. Calling it after configuring will not restore defaults - it will do nothing to any key you already set. Call it first if you want defaults underneath your overrides, or at any point if you only want the gaps filled.
Does NOT clear previously registered hooks - it seeds value defaults, not hook registrations.
Refused once frozen.
- Threading:
State transitions are applied under the configuration lock.
- Lifecycle / Cleanup:
Guarded by check_cleaned().
- Raises:
RuntimeError -- If the configuration has been cleaned.
- Returns:
This same configuration instance (for chaining).
- Return type:
- with_disposal(enabled: bool = True) SpellbookConfiguration[source]ο
Enable or disable disposal features and return self.
- Parameters:
enabled -- True to enable disposal semantics; False to disable.
- Returns:
This same configuration instance (for chaining).
- Return type:
Contract:
Writes only the disposal flag.
Returns self for chaining.
- with_enforce_priority_disposal_methods(enabled: bool = True) SpellbookConfiguration[source]ο
Store the disposal-method group priority and return this configuration.
- Parameters:
enabled -- True places matching book methods before spell-only methods. False (the configuration default) places the book block last; it does not disable the book's contribution. In both modes, shared names occur only in the book block, in configuration order.
Contract:
Stages policy only; does not match methods or invoke disposal.
Both groups keep their own order; shared names belong to the book.
May be changed during assembly; the existing freeze boundary seals it.
Bool type checking occurs during validate/finalize, without coercion.
- Threading:
Uses set_property's existing configuration mutation lock.
- Raises:
RuntimeError -- If this configuration is frozen or cleaned.
- Returns:
This same instance for fluent chaining.
- Return type:
- with_disposal_method_names(names: list[str]) SpellbookConfiguration[source]ο
Replace the entire list of disposal method names and return self.
Example
cfg.with_disposal_method_names(["close", "cleanup"])
- Parameters:
names -- Full replacement list of method names (strings).
- Returns:
This same configuration instance (for chaining).
- Return type:
Contract:
Replaces the entire disposal-method list.
Type-checks the container before writing it.
- add_disposal_methods(*names: str) SpellbookConfiguration[source]ο
Append one or more disposal method names (deduplicated, order-preserving) and return self.
Behaviour:
Initializes the list to [] if unset.
Preserves existing order; adds new names at the end if not already present.
- Parameters:
*names -- One or more method names to add.
- Returns:
This same configuration instance (for chaining).
- Return type:
Contract:
Initializes the disposal-method list when absent.
Preserves order while deduplicating names.
- finalize() SpellbookConfiguration[source]ο
Validate and freeze, returning self.
- Returns:
This same configuration instance (for chaining).
- Return type:
Contract:
Runs the full validation pipeline.
Freezes the configuration on success.
Returns self for chaining.
- build() SpellbookConfiguration[source]ο
Fluent alias for finalize().
Contract:
Performs the same validation-and-freeze behaviour as finalize().
Returns self for chaining.
- Returns:
- This configuration, validated and frozen. Must be
frozen before a Conduit can be conjured.
- Return type: