Skip to content

Commit 4e95492

Browse files
committed
fix: un-xfail intent-layers e2e + harden utterance.handled test, bump pins
Root cause of the intent-layers e2e XFAILs is an upstream regression in ovos-utils (#393 / 9317a8d): FakeBus.on_message dropped the 'if sess.session_id != "default"' guard that the real MessageBusClient.on_message still keeps, so the default session is folded on every received message, wiping every in-place add_context mutation (intent-layer tokens included). Fixed in OpenVoiceOS/ovos-utils#395. - test_intent_layers_e2e.py: revert the xfail markers added in this PR; both tests pass once ovos-utils >= 0.13.3a2 lands. - test_base.py: replace test_on_event_end_is_intent_still_emits_utterance_handled (stale vs PIPELINE-1 §9.5) with two deterministic branches: * _defers_utterance_handled_to_core — modern core (>=2.3.0a1) owns the end-marker, so workshop must NOT also emit ovos.utterance.handled. * _emits_utterance_handled_legacy — absent/old core, workshop still emits (migration-window back-compat). Both monkeypatch _core_owns_utterance_handled. - pyproject.toml: bump floors to the latest alphas that carry the singleton-registry SessionManager + §9.5 orchestrator ownership: ovos-utils >= 0.13.3a2, ovos_bus_client >= 2.6.2a2, ovos-spec-tools >= 1.2.3a1, ovos-core >= 2.4.0a1 (test), ovos-adapt-parser >= 1.4.2a1 (test).
1 parent 2aee2bd commit 4e95492

3 files changed

Lines changed: 36 additions & 21 deletions

File tree

pyproject.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ license = "apache-2.0"
1111
authors = [{name = "jarbasAi", email = "jarbasai@mailfence.com"}]
1212
requires-python = ">=3.9"
1313
dependencies = [
14-
"ovos-utils>= 0.7.0,<1.0.0",
15-
"ovos_bus_client>=2.6.0a1,<3.0.0", # HandlerLifecycle done-signal util (#246)
14+
"ovos-utils>= 0.13.3a2,<1.0.0", # FakeBus default-session fold guard (ovos-utils#395) — keeps intent-layer context tokens alive
15+
"ovos_bus_client>=2.6.2a2,<3.0.0", # HandlerLifecycle done-signal util (#246) + singleton-registry SessionManager (2.6.2a2)
1616
"ovos-config>=0.0.12,<3.0.0",
17-
"ovos-spec-tools>=0.16.1a2", # carries the adapt-free intent-definition primitives (OVOS-INTENT-4)
17+
"ovos-spec-tools>=1.2.3a1", # canonical SessionManager registry + OVOS-INTENT-4 intent-definition primitives
1818
"ovos-yes-no-plugin>=0.3.0,<1.0.0",
1919
"ovos-option-matcher-fuzzy-plugin>=0.0.1,<1.0.0",
2020
"ovos-number-parser>=0.0.1,<1.0.0",
@@ -26,9 +26,9 @@ dependencies = [
2626

2727
[project.optional-dependencies]
2828
test = [
29-
"ovos-core>=0.0.8a50",
29+
"ovos-core>=2.4.0a1", # orchestrator owns ovos.utterance.handled on the matched path (PIPELINE-1 §9.5)
3030
"ovoscope>=0.1.0",
31-
"ovos-adapt-parser>=1.3.1a1",
31+
"ovos-adapt-parser>=1.4.2a1",
3232
"pytest",
3333
"pytest-cov",
3434
"ovos-translate-server-plugin",

test/unittests/skills/test_base.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -355,16 +355,41 @@ def test_on_event_end(self):
355355
self.assertEqual(context["skill_id"], self.skill_id)
356356
self.assertEqual(context["session"]["session_id"], "sess1")
357357

358-
def test_on_event_end_is_intent_still_emits_utterance_handled(self):
359-
# the ovos.utterance.handled emission must be PRESERVED alongside the
360-
# delegated .complete done-signal when is_intent=True
358+
def test_on_event_end_intent_defers_utterance_handled_to_core(self):
359+
# PIPELINE-1 §9.5: with a modern ovos-core (>=2.3.0a1) the orchestrator
360+
# owns the universal `ovos.utterance.handled` end-marker on every
361+
# terminal path — the matched path included. Workshop must NOT also
362+
# emit it (consumers would see the marker twice); only the delegated
363+
# `mycroft.skill.handler.complete` done-signal is emitted here.
364+
from unittest.mock import patch
361365
from ovos_bus_client.message import Message
362366
from ovos_spec_tools import SpecMessage
363367
msg = Message("trigger", {}, {})
364368
skill_data = {"name": "TestSkill.handle_test"}
365-
captured = self._capture(OVOSSkill._on_event_end, msg,
366-
"mycroft.skill.handler", dict(skill_data),
367-
True)
369+
with patch("ovos_workshop.skills.ovos._core_owns_utterance_handled",
370+
return_value=True):
371+
captured = self._capture(OVOSSkill._on_event_end, msg,
372+
"mycroft.skill.handler",
373+
dict(skill_data), True)
374+
types = [c[0] for c in captured]
375+
self.assertIn("mycroft.skill.handler.complete", types)
376+
self.assertNotIn(SpecMessage.UTTERANCE_HANDLED.value, types)
377+
378+
def test_on_event_end_intent_emits_utterance_handled_legacy(self):
379+
# Migration-window back-compat: with an absent/old ovos-core that does
380+
# not yet emit `ovos.utterance.handled` on the matched path, workshop
381+
# must still emit it alongside the delegated `.complete` done-signal so
382+
# spec consumers always observe exactly one end-marker.
383+
from unittest.mock import patch
384+
from ovos_bus_client.message import Message
385+
from ovos_spec_tools import SpecMessage
386+
msg = Message("trigger", {}, {})
387+
skill_data = {"name": "TestSkill.handle_test"}
388+
with patch("ovos_workshop.skills.ovos._core_owns_utterance_handled",
389+
return_value=False):
390+
captured = self._capture(OVOSSkill._on_event_end, msg,
391+
"mycroft.skill.handler",
392+
dict(skill_data), True)
368393
types = [c[0] for c in captured]
369394
self.assertIn("mycroft.skill.handler.complete", types)
370395
self.assertIn(SpecMessage.UTTERANCE_HANDLED.value, types)

test/unittests/skills/test_intent_layers_e2e.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,6 @@ def _tokens(self):
177177
SessionManager.default_session.context.get_context()]
178178

179179
# tests ------------------------------------------------------------------
180-
@pytest.mark.xfail(reason="pre-existing failure on dev, unrelated to "
181-
"OVOS-INTENT-4 producer changes: layer context "
182-
"token is never applied, so gated intents never "
183-
"match (ovos_workshop/decorators/layers.py)",
184-
strict=False)
185180
def test_layers_advance_in_sequence_and_gate_intents(self):
186181
skill = self.skill
187182

@@ -238,11 +233,6 @@ def test_layers_advance_in_sequence_and_gate_intents(self):
238233
self.assertEqual(skill.reached,
239234
["begin", "layer0", "layer1", "layer2", "layer3"])
240235

241-
@pytest.mark.xfail(reason="pre-existing failure on dev, unrelated to "
242-
"OVOS-INTENT-4 producer changes: layer context "
243-
"token is never applied, so gated intents never "
244-
"match (ovos_workshop/decorators/layers.py)",
245-
strict=False)
246236
def test_inactive_layer_intents_do_not_match(self):
247237
"""With only layer0 active, layer1/2/3 intents must not be selectable."""
248238
skill = self.skill

0 commit comments

Comments
 (0)