generated from coulomb/repo-seed
engine/adapter.py: EngineShardAdapter implements adapters.ShardAdapter (read/write run extension transform hooks; profile derived from active extensions, E-5; current_rev for apply-under-drift) + build_engine_shard() helper (explicit ids or activation provider). runtime.available() added. Engine shard passes assert_conformant and attaches to an InformationSpace — resolve + edit (overlay->apply->write-through) work, and the declared profile reflects the active extensions. 5 tests green, pyflakes clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
83 lines
3.1 KiB
Python
83 lines
3.1 KiB
Python
"""EngineShardAdapter — the engine exposed as a canonical-mode shard (WikiEngineCoreArchitecture
|
|
§6, E-1/E-5).
|
|
|
|
The engine is *one shard*: the orchestrator consumes it only through this `ShardAdapter`. The
|
|
adapter is backed by the kernel (T1) + a composed extension set (T2/T3); its §A capability
|
|
profile is **derived from the active extensions** (T4), so the orchestrator sees an honest,
|
|
conformance-verifiable profile that reflects exactly what is activated. Read/write run the
|
|
extensions' transform hooks; everything above this stays in the orchestrator (no union/projection
|
|
import).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Iterable
|
|
|
|
from shard_wiki.adapters import ShardAdapter
|
|
from shard_wiki.engine.activation import ActivationContext, ActivationProvider, ActivationResolver
|
|
from shard_wiki.engine.extension import ActiveExtensions, ExtensionRuntime, Hook
|
|
from shard_wiki.engine.kernel import EngineKernel
|
|
from shard_wiki.engine.profile import derive_profile
|
|
from shard_wiki.model import CapabilityProfile, NotSupported, Page, Verb
|
|
|
|
__all__ = ["EngineShardAdapter", "build_engine_shard"]
|
|
|
|
|
|
class EngineShardAdapter(ShardAdapter):
|
|
def __init__(
|
|
self,
|
|
kernel: EngineKernel,
|
|
active: ActiveExtensions,
|
|
base_profile: CapabilityProfile | None = None,
|
|
) -> None:
|
|
self._kernel = kernel
|
|
self._active = active
|
|
self._profile = derive_profile(active, base_profile) # validated (E-5)
|
|
|
|
@property
|
|
def shard_id(self) -> str:
|
|
return self._kernel.shard_id
|
|
|
|
def profile(self) -> CapabilityProfile:
|
|
return self._profile
|
|
|
|
def keys(self) -> Iterable[str]:
|
|
return self._kernel.keys()
|
|
|
|
def read(self, key: str) -> Page:
|
|
page = self._kernel.read(key)
|
|
return self._active.dispatch_transform(Hook.ON_READ, page, {"shard_id": self.shard_id})
|
|
|
|
def current_rev(self, key: str) -> str | None:
|
|
return self._kernel.current_rev(key)
|
|
|
|
def write(self, key: str, body: str) -> Page:
|
|
if not self._profile.supports(Verb.WRITE):
|
|
raise NotSupported(f"{type(self).__name__} ({self.shard_id}) is read-only")
|
|
body = self._active.dispatch_transform(
|
|
Hook.ON_WRITE, body, {"shard_id": self.shard_id, "key": key}
|
|
)
|
|
return self._kernel.write(key, body)
|
|
|
|
|
|
def build_engine_shard(
|
|
shard_id: str,
|
|
runtime: ExtensionRuntime,
|
|
*,
|
|
activate: Iterable[str] | None = None,
|
|
provider: ActivationProvider | None = None,
|
|
context: ActivationContext | None = None,
|
|
base_profile: CapabilityProfile | None = None,
|
|
) -> EngineShardAdapter:
|
|
"""Stand up an engine shard: resolve which extensions are active (explicit ``activate`` ids,
|
|
or via an activation ``provider`` over the runtime's available set), compose them, and wrap a
|
|
fresh kernel as a `ShardAdapter`.
|
|
"""
|
|
if provider is not None:
|
|
ctx = context or ActivationContext(shard_id)
|
|
ids = ActivationResolver(provider).active_extensions(runtime.available(), ctx)
|
|
else:
|
|
ids = set(activate or ())
|
|
active = runtime.activate(ids)
|
|
return EngineShardAdapter(EngineKernel(shard_id), active, base_profile)
|