From 834aa613b158550edcbf99baf9609dff90b1c9e1 Mon Sep 17 00:00:00 2001 From: anti Date: Fri, 8 May 2026 18:51:30 -0400 Subject: [PATCH] feat(pyproject): pin decnet-behave-{core,shell} >=0.1.0,<0.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lock the BEHAVE library versions per BEHAVE-INTEGRATION.md §Versioning. The profiler worker (Phase 4 wiring) imports `Observation`/`Window` from `decnet_behave_core.spec.envelope` and `event_topic_for`/`to_event_payload` from `decnet_behave_shell.spec.event_adapter`; without the pin a broken wheel or missing install would only show up on first publish. Four-test smoke pins the public surface: envelope construction, registry import non-empty, event-adapter topic shape, and the adapter's id/ts/v exclusion contract. --- pyproject.toml | 6 ++ tests/profiler/behave_shell/test_pin_smoke.py | 57 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 tests/profiler/behave_shell/test_pin_smoke.py diff --git a/pyproject.toml b/pyproject.toml index 095bb73c..be620458 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,6 +47,12 @@ dependencies = [ # platform-marker keeps macOS/Windows installs from pulling a # never-imported wheel. "asyncinotify>=4.0 ; sys_platform == 'linux'", + # BEHAVE — out-of-tree behavioural-observation framework. core ships + # the Observation envelope; shell ships the primitive registry + + # bus event adapter consumed by decnet/profiler/behave_shell/. Pin + # range tracks BEHAVE-INTEGRATION.md §"Versioning". + "decnet-behave-core>=0.1.0,<0.2", + "decnet-behave-shell>=0.1.0,<0.2", ] [project.optional-dependencies] diff --git a/tests/profiler/behave_shell/test_pin_smoke.py b/tests/profiler/behave_shell/test_pin_smoke.py new file mode 100644 index 00000000..3de76955 --- /dev/null +++ b/tests/profiler/behave_shell/test_pin_smoke.py @@ -0,0 +1,57 @@ +"""W.2 smoke: BEHAVE library pins are install-time importable. + +Three asserts protect the pyproject.toml pin from a broken wheel / +missing install / drift in the BEHAVE-side public API. CI catches +these before they make it onto a running master. +""" +from __future__ import annotations + + +def test_envelope_imports_cleanly() -> None: + from decnet_behave_core.spec.envelope import Observation, Window + # construction smoke — registry-agnostic envelope + obs = Observation( + primitive="motor.input_modality", + value="typed", + confidence=0.9, + window=Window(start_ts=0.0, end_ts=1.0), + source="test", + ) + assert obs.primitive == "motor.input_modality" + assert obs.v >= 1 + + +def test_registry_imports_and_is_non_empty() -> None: + from decnet_behave_shell.spec.primitives import PRIMITIVE_REGISTRY + assert len(PRIMITIVE_REGISTRY) > 0 + # spot-check a primitive every Tier-A engine emits + assert "motor.input_modality" in PRIMITIVE_REGISTRY + + +def test_event_adapter_topic_shape() -> None: + from decnet_behave_shell.spec.event_adapter import event_topic_for + assert ( + event_topic_for("motor.input_modality") + == "attacker.observation.motor.input_modality" + ) + + +def test_to_event_payload_excludes_envelope_meta_fields() -> None: + """The adapter excludes id/ts/v from payload (they ride at the + DECNET Event envelope level). The profiler worker re-merges them + in per BEHAVE-INTEGRATION.md §339-366.""" + from decnet_behave_core.spec.envelope import Observation, Window + from decnet_behave_shell.spec.event_adapter import to_event_payload + obs = Observation( + primitive="motor.input_modality", + value="typed", + confidence=0.9, + window=Window(start_ts=0.0, end_ts=1.0), + source="test", + ) + payload = to_event_payload(obs) + for excluded in ("id", "ts", "v"): + assert excluded not in payload, ( + f"event_adapter.to_event_payload leaked {excluded!r} into " + f"the payload body — DECNET re-merges these explicitly" + )