# SPDX-License-Identifier: GPL-3.0-or-later """BEHAVE-SHELL Observation envelope (registry-aware subclass). The base envelope (`Observation`, `Window`, `OBSERVATION_SCHEMA_VERSION`, `ObservationValue`) lives in `decnet-behave-core`; it enforces only structural invariants (window ordering, confidence bounds, schema version, no extras). This module subclasses the core `Observation` to add registry-aware validation against `BEHAVE-SHELL`'s `PRIMITIVE_REGISTRY`. The subclass is exported under the same name `Observation` so existing imports (``from spec.envelope import Observation``) continue to resolve to the registry-validated form without consumer changes. PII discipline (lifted from DECNET ``attackers.py:268-285,308-311``) — see the core envelope module docstring for the binding statement. """ from __future__ import annotations from pydantic import model_validator from decnet_behave_core.spec.envelope import ( OBSERVATION_SCHEMA_VERSION, ObservationValue, Window, ) from decnet_behave_core.spec.envelope import Observation as _BaseObservation from .primitives import PRIMITIVE_REGISTRY class Observation(_BaseObservation): """Shell-domain Observation: base envelope + BEHAVE-SHELL registry check.""" @model_validator(mode="after") def _validate_against_shell_registry(self) -> "Observation": spec = PRIMITIVE_REGISTRY.get(self.primitive) if spec is None: raise ValueError( f"unknown primitive {self.primitive!r}; " f"add it to spec/primitives.py:PRIMITIVE_REGISTRY first" ) try: spec.validate_value(self.value) except ValueError as exc: raise ValueError( f"value invalid for primitive {self.primitive!r}: {exc}" ) from None return self __all__ = [ "OBSERVATION_SCHEMA_VERSION", "Observation", "ObservationValue", "Window", ]