Skip to content

fix: normalize pipeline ids when matching session blacklists - #854

Merged
JarbasAl merged 1 commit into
devfrom
fix/session-pipeline-blacklist-normalization
Aug 31, 2026
Merged

JarbasAl merged 1 commit into
devfrom
fix/session-pipeline-blacklist-normalization

Conversation

@JarbasAl

@JarbasAl JarbasAl commented Aug 12, 2026

Copy link
Copy Markdown
Member

🤖 Auto-generated by Claude Fable 5 (claude-fable-5, review and orchestration) with Claude Sonnet 5 (claude-sonnet-5, edits) via Claude Code — NOT human-reviewed. Verify before acting.

get_pipeline() compared session.blacklisted_pipelines entries against session.pipeline matcher ids as literal strings. A deployment blacklist is naturally expressed in installed plugin ids (ovos-adapt-pipeline-plugin), while a session pipeline carries confidence-suffixed matcher ids (ovos-adapt-pipeline-plugin-high), so a bare plugin id in the blacklist silently failed to block any of its suffixed matcher variants. In addition, a confidence-suffixed blacklist entry itself — legacy spelling (adapt_high) or canonical (ovos-adapt-pipeline-plugin-high) — only denied that one tier, leaving the plugin's other tiers invokable in the same session.

OVOS-PIPELINE-1 §3 and §5.2 are explicit that a blacklisted_pipelines entry names the plugin, a single actor, never a specific matcher configuration of it: a plugin cannot be denied in one confidence tier and invoked in another.

The fix normalizes both sides of the comparison to a bare plugin id before checking membership: each blacklist entry is passed through _PIPELINE_MIGRATION_MAP (legacy short id -> canonical id) and then has its confidence suffix stripped by _PIPELINE_RE, and the matcher id under test is normalized and stripped the same way. is_blacklisted() then only tests plugin-id membership, so a bare or suffixed, legacy or canonical, blacklist entry now denies every confidence tier of the plugin it names.

Two regression tests were added to test/unittests/test_intent_service_extended.py: one blacklists the legacy suffixed id adapt_high and one the canonical suffixed id ovos-adapt-pipeline-plugin-medium, in both cases against a session pipeline listing all three adapt tiers plus fallback_high; both assert only fallback_high survives and that get_pipeline_matcher is called exactly once, with fallback_high. Reverting only the source change (git apply -R against the source diff, keeping the tests) made both new tests fail with an AssertionError showing the adapt matchers still present in the result (e.g. ['ovos-adapt-pipeline-plugin-medium', 'ovos-adapt-pipeline-plugin-low', 'fallback_high'] != ['fallback_high']); restoring the fix made them pass. The full test/unittests/test_intent_service_extended.py and test/unittests/test_intent_service.py suites were run after the fix: 88 passed (9 subtests), no regressions.

docs/prerelease-quirks.md gained an entry stating that a session blacklist entry now denies the whole plugin regardless of tier spelling, legacy or canonical.

@github-actions github-actions Bot added the fix label Aug 12, 2026
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 17 minutes.

View limit details

Limit details: You’ve used all 2 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3b215d8a-f994-4e2b-97e6-9f892d8c28c0

📥 Commits

Reviewing files that changed from the base of the PR and between 0a19a32 and a6ae7fb.

📒 Files selected for processing (3)
  • docs/prerelease-quirks.md
  • ovos_core/intent_services/service.py
  • test/unittests/test_intent_service_extended.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown

Hello! The automated checks have been performed. 👋

I've aggregated the results of the automated checks for this PR below.

📚 Docs

Ensuring the codebase remains stable and healthy. 🛡️

✅ All required documentation files present.

README.md

📋 Repo Health

Evaluating the repository's overall condition. 📋

✅ All required files present.

Latest Version: 3.0.9a1

ovos_core/version.py — Version file
README.md — README
LICENSE — License file
pyproject.toml — pyproject.toml
⚠️ setup.py — setup.py
CHANGELOG.md — Changelog
ovos_core/version.py has valid version block markers

🔎 Type Check

I've got some results for you! 📝

mypy: 300 error(s) found

ovos_core/main.py:24:1: error: Skipping analyzing "ovos_utils.log": module is installed, but missing library stubs or py.typed marker [import-untyped]

Errors (showing first 10/300)
test/unittests/test_skill/__init__.py:15:1: error: Skipping analyzing "ovos_workshop.skills.ovos": module is installed, but missing library stubs or py.typed marker  [import-untyped]
test/end2end/conftest.py:10:1: error: Cannot find implementation or library stub for module named "pytest"  [import-not-found]
ovos_core/transformers.py:3:1: error: Skipping analyzing "ovos_config": module is installed, but missing library stubs or py.typed marker  [import-untyped]
ovos_core/transformers.py:4:1: error: Skipping analyzing "ovos_plugin_manager.intent_transformers": module is installed, but missing library stubs or py.typed marker  [import-untyped]
ovos_core/transformers.py:5:1: error: Skipping analyzing "ovos_plugin_manager.metadata_transformers": module is installed, but missing library stubs or py.typed marker  [import-untyped]
ovos_core/transformers.py:6:1: error: Skipping analyzing "ovos_plugin_manager.text_transformers": module is installed, but missing library stubs or py.typed marker  [import-untyped]
ovos_core/transformers.py:7:1: error: Skipping analyzing "ovos_plugin_manager.transformer_services": module is installed, but missing library stubs or py.typed marker  [import-untyped]
ovos_core/intent_services/manifest.py:17:1: error: Skipping analyzing "ovos_bus_client.message": module is installed, but missing library stubs or py.typed marker  [import-untyped]
ovos_core/intent_services/manifest.py:18:1: error: Skipping analyzing "ovos_spec_tools": module is installed, but missing library stubs or py.typed marker  [import-untyped]
ovos_core/intent_services/manifest.py:19:1: error: Skipping analyzing "ovos_utils.log": module is installed, but missing library stubs or py.typed marker  [import-untyped]

🏷️ Release Preview

Checking if we're ready for the big release. 🏁

Current: 3.0.9a1Next: 3.0.10a1

Signal Value
Label fix
PR title fix: normalize pipeline ids when matching session blacklists
Bump build

✅ PR title follows conventional commit format.


🚀 Release Channel Compatibility

Predicted next version: 3.0.10a1

Channel Status Note Current Constraint
Stable Too new (must be <1.4.0) ovos-core>=1.3.1,<1.4.0
Testing Too new (must be <3.0.0) ovos-core>=2.1.1,<3.0.0
Alpha Compatible ovos-core>=2.2.4a1

🌍 Locale Build

Just a little bit of automation magic for you. ✨

✅ Locale properly configured (64 files, 17 languages)

Locale directories found:

  • ovos_core/intent_services/locale

Localization coverage:

  • ovos_core/intent_services/locale: 64 files in 17 languages (en-us, ca-es, fa-ir, de-de, gl-es...)

pyproject.toml:[tool.setuptools.package-data.ovos_core] includes locale

  • intent_services/locale/*/*.voc

Build manifest: ✅ 31 locale files included in package

📊 Coverage

Scanning the codebase for untested secrets... 🕵️

⚠️ 72.5% total coverage

Files below 80% coverage (8 files)
File Coverage Missing lines
ovos_core/__init__.py 0.0% 7
ovos_core/__main__.py 0.0% 26
ovos_core/intent_services/__init__.py 0.0% 1
ovos_core/transformers.py 33.3% 18
ovos_core/skill_installer.py 45.3% 134
ovos_core/skill_manager.py 62.5% 155
ovos_core/intent_services/service.py 71.1% 147
ovos_core/intent_services/dispatcher.py 75.7% 27

Full report: download the coverage-report artifact.

🔌 Plugin Detection

I've verified the plugin's 'versioning' logic. 🏷️

Plugin Status: ERRORS (1)

Plugin Info:

  • Name: ovos-core
  • Description: The spiritual successor to Mycroft AI, OVOS is flexible voice assistant software that can be run almost anywhere!

OPM Detection:

Plugin Type Wheel Editable
pipeline

Entry Point Validation:

Entry Point Type Import Interface
ovos-converse-pipeline-plugin pipeline ✅ 1103ms
ovos-fallback-pipeline-plugin pipeline ✅ 2ms
ovos-stop-pipeline-plugin pipeline ✅ 57ms

⊘ No settingsmeta.json
requires-python >=3.10 — running Python 3.11

Issues:

  • ❌ Import time for ovos-converse-pipeline-plugin exceeds 500ms (1103ms)
  • ⚠️ No settingsmeta.json found
  • ⚠️ No settingsmeta.json found

🔒 Security (pip-audit)

I've checked the firewalls of your PR. 🔥

✅ No known vulnerabilities found (112 packages scanned).

🔨 Build Tests

Running the final assembly check. 🔧

✅ All versions pass

Python Build Install Tests
3.10
3.11
3.12
3.13
3.14

🔌 Skill Tests (ovoscope)

I ran the end-to-end skill tests to see how your skill behaves in the real world! 🎤

13/37 passed

❌ **TestAdaptIntent** — 0/4
Test Result
test_intent_blacklist ❌ subtests passed
test_padatious_no_match ❌ subtests passed
test_skill_blacklist ❌ subtests passed
test_adapt_match ❌ subtests passed

test_intent_blacklist failure:

[gw0] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python

test_padatious_no_match failure:

[gw1] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python

test_skill_blacklist failure:

[gw3] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python
❌ **TestCancelIntentMidSentence** — 0/1
Test Result
test_cancel_match ❌ subtests passed

test_cancel_match failure:

[gw0] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python
✅ **TestContext1EndToEndReachability** — 3/3
❌ **TestConverse** — 0/1
Test Result
test_parrot_mode ❌ subtests passed

test_parrot_mode failure:

[gw2] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python
❌ **TestDeactivate** — 2/3
Test Result
test_activate ✅ passed
test_deactivate ✅ passed
test_deactivate_inside_converse ❌ subtests passed

test_deactivate_inside_converse failure:

[gw3] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python
❌ **TestFallback** — 0/1
Test Result
test_fallback_match ❌ subtests passed

test_fallback_match failure:

[gw1] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python
✅ **TestGGWaveSkillInstall** — 2/2 ✅ **TestGlobalStopSpec** — 1/1
❌ **TestIntentPipelineRouting** — 0/4
Test Result
test_blacklisted_skill_falls_through_to_failure ❌ subtests passed
test_high_priority_stage_handles_before_low ❌ subtests passed
test_padatious_intent_matched ❌ subtests passed
test_no_match_produces_intent_failure ❌ subtests passed

test_blacklisted_skill_falls_through_to_failure failure:

[gw2] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python

test_high_priority_stage_handles_before_low failure:

[gw1] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python

test_padatious_intent_matched failure:

[gw3] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python
❌ **TestLangDisambiguation** — 0/4
Test Result
test_metadata_preferred_over_text_detection ❌ subtests passed
test_lang_text_detection ❌ subtests passed
test_stt_lang ❌ subtests passed
test_invalid_lang_detection ❌ subtests passed

test_metadata_preferred_over_text_detection failure:

[gw2] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python

test_lang_text_detection failure:

[gw0] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python

test_stt_lang failure:

[gw1] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python
✅ **TestLegacyGlobalStop** — 1/1
❌ **TestLegacyIntentIdBackCompat** — 0/2
Test Result
test_legacy_dispatch_topic_fires_handler ❌ subtests passed
test_legacy_blacklist_id_suppresses ❌ subtests passed

test_legacy_dispatch_topic_fires_handler failure:

[gw3] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python

test_legacy_blacklist_id_suppresses failure:

[gw2] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python
✅ **TestLegacyTargetedStop** — 1/1
❌ **TestNoSkills** — 0/2
Test Result
test_complete_failure ❌ subtests passed
test_routing ❌ subtests passed

test_complete_failure failure:

[gw3] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python

test_routing failure:

[gw0] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python
❌ **TestPadatiousIntent** — 0/4
Test Result
test_adapt_no_match ❌ subtests passed
test_skill_blacklist ❌ subtests passed
test_padatious_match ❌ subtests passed
test_intent_blacklist ❌ subtests passed

test_adapt_no_match failure:

[gw1] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python

test_skill_blacklist failure:

[gw2] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python

test_padatious_match failure:

[gw1] linux -- Python 3.11.16 /opt/hostedtoolcache/Python/3.11.16/x64/bin/python
✅ **TestResponseModeHolderStopE2E** — 2/2 ✅ **TestTargetedStopSpec** — 1/1

🚌 Bus Coverage

A deep dive into the skill's communication patterns. 🌊

🔴 Coverage Summary

Metric Status Coverage
Listeners ░░░░░░░░░░ 8.8% 16/182 handlers
Emitters ██████████ 100% 25/25 observed
Assertions ██████████ 100% 25/25 asserted

📊 Per-Skill Breakdown

Skill Listeners Observed Asserted
AdaptPipeline 0/14 (0.0%) 0/0 0/0
ConverseService 0/4 (0.0%) 0/0 0/0
DomainAdaptPipeline 0/14 (0.0%) 0/0 0/0
FallbackService 0/2 (0.0%) 0/0 0/0
HierarchicalAdaptPipeline 0/14 (0.0%) 0/0 0/0
IntentDispatcher 1/2 (50.0%) 0/0 0/0
IntentManifest 0/8 (0.0%) 0/0 0/0
IntentService 1/4 (25.0%) 0/0 0/0
Model2VecPrototypePipeline 0/12 (0.0%) 0/0 0/0
PadaciosoPipeline 0/11 (0.0%) 0/0 0/0
PadatiousPipeline 0/15 (0.0%) 0/0 0/0
SkillManager 0/5 (0.0%) 0/0 0/0
_LegacyStopBridge 3/3 (100.0%) 0/0 0/0
__core__ 4/26 (15.4%) 6/6 6/6
ovos-skill-count.openvoiceos 3/20 (15.0%) 0/0 0/0
ovos-skill-hello-world.openvoiceos 2/24 (8.3%) 9/9 9/9
ovos-stop-pipeline-plugin 0/0 (0.0%) 3/3 3/3
stop.openvoiceos 0/0 (0.0%) 7/7 7/7
type 2/4 (50.0%) 0/0 0/0
🔍 Detailed Message Type Breakdown

AdaptPipeline

⚠️ Uncovered Listeners:

  • ovos.intent.deregister (Intent)
  • ovos.intent.disable (Intent)
  • ovos.intent.enable (Intent)
  • ovos.intent.register.keyword (Intent)
  • detach_intent
  • detach_skill
  • intent.service.adapt.get
  • intent.service.adapt.manifest.get
  • intent.service.adapt.vocab.manifest.get
  • ovos.entity.deregister
  • ovos.entity.register
  • ovos.skill.deregister
  • register_intent
  • register_vocab

ConverseService

⚠️ Uncovered Listeners:

  • converse:skill (Intent)
  • intent.service.active_skills.get
  • intent.service.skills.activate
  • intent.service.skills.deactivate

DomainAdaptPipeline

⚠️ Uncovered Listeners:

  • ovos.intent.deregister (Intent)
  • ovos.intent.disable (Intent)
  • ovos.intent.enable (Intent)
  • ovos.intent.register.keyword (Intent)
  • detach_intent
  • detach_skill
  • intent.service.adapt.get
  • intent.service.adapt.manifest.get
  • intent.service.adapt.vocab.manifest.get
  • ovos.entity.deregister
  • ovos.entity.register
  • ovos.skill.deregister
  • register_intent
  • register_vocab

FallbackService

⚠️ Uncovered Listeners:

  • ovos.skills.fallback.deregister
  • ovos.skills.fallback.register

HierarchicalAdaptPipeline

⚠️ Uncovered Listeners:

  • ovos.intent.deregister (Intent)
  • ovos.intent.disable (Intent)
  • ovos.intent.enable (Intent)
  • ovos.intent.register.keyword (Intent)
  • detach_intent
  • detach_skill
  • intent.service.adapt.get
  • intent.service.adapt.manifest.get
  • intent.service.adapt.vocab.manifest.get
  • ovos.entity.deregister
  • ovos.entity.register
  • ovos.skill.deregister
  • register_intent
  • register_vocab

IntentDispatcher

⚠️ Uncovered Listeners:

  • mycroft.skill.handler.error
    ✅ Covered Listeners:
  • mycroft.skill.handler.complete (9x)

IntentManifest

⚠️ Uncovered Listeners:

  • ovos.intent.deregister (Intent)
  • ovos.intent.describe (Intent)
  • ovos.intent.disable (Intent)
  • ovos.intent.enable (Intent)
  • ovos.intent.list (Intent)
  • ovos.intent.register.keyword (Intent)
  • ovos.intent.register.template (Intent)
  • ovos.skill.deregister

IntentService

⚠️ Uncovered Listeners:

  • intent.service.intent.get (Intent)
  • intent.service.pipelines.reload
  • intent.service.skills.deactivate
    ✅ Covered Listeners:
  • ovos.utterance.handle (9x)

Model2VecPrototypePipeline

⚠️ Uncovered Listeners:

  • ovos.intent.deregister (Intent)
  • ovos.intent.disable (Intent)
  • ovos.intent.enable (Intent)
  • ovos.intent.register.template (Intent)
  • padatious:register_intent (Intent)
  • detach_intent
  • detach_skill
  • mycroft.ready
  • ovos.entity.deregister
  • ovos.entity.register
  • ovos.skill.deregister
  • register_intent

PadaciosoPipeline

⚠️ Uncovered Listeners:

  • ovos.intent.deregister (Intent)
  • ovos.intent.disable (Intent)
  • ovos.intent.enable (Intent)
  • ovos.intent.register.template (Intent)
  • padatious:register_entity (Intent)
  • padatious:register_intent (Intent)
  • detach_intent
  • detach_skill
  • ovos.entity.deregister
  • ovos.entity.register
  • ovos.skill.deregister

PadatiousPipeline

⚠️ Uncovered Listeners:

  • ovos.intent.deregister (Intent)
  • ovos.intent.disable (Intent)
  • ovos.intent.enable (Intent)
  • ovos.intent.register.template (Intent)
  • padatious:register_entity (Intent)
  • padatious:register_intent (Intent)
  • detach_intent
  • detach_skill
  • intent.service.padatious.entities.manifest.get
  • intent.service.padatious.get
  • intent.service.padatious.manifest.get
  • mycroft.skills.train
  • ovos.entity.deregister
  • ovos.entity.register
  • ovos.skill.deregister

SkillManager

⚠️ Uncovered Listeners:

  • skill.converse.get_response.disable
  • skillmanager.activate
  • skillmanager.deactivate
  • skillmanager.keep
  • skillmanager.list

_LegacyStopBridge

✅ Covered Listeners:

  • ovos.intent.matched (5x)
  • stop:global (2x)
  • stop:skill (1x)

__core__

⚠️ Uncovered Listeners:

  • add_context
  • clear_context
  • message
  • mycroft.ovos-skill-count.openvoiceos.all_loaded
  • mycroft.ovos-skill-count.openvoiceos.is_alive
  • mycroft.ovos-skill-count.openvoiceos.is_ready
  • mycroft.ovos-skill-hello-world.openvoiceos.all_loaded
  • mycroft.ovos-skill-hello-world.openvoiceos.is_alive
  • mycroft.ovos-skill-hello-world.openvoiceos.is_ready
  • ovos-skill-count.openvoiceos.set
  • ovos-skill-count.openvoiceos.stop.response
  • ovos-skill-hello-world.openvoiceos.set
  • ovos.ggwave.disable
  • ovos.ggwave.enable
  • ovos.pip.install
  • ovos.pip.uninstall
  • ovos.session.sync
  • ovos.skills.install
  • ovos.skills.uninstall
  • ovos.stop.pong
  • remove_context
  • skill.converse.get_response.enable
    ✅ Covered Listeners:
  • ovos-stop-pipeline-plugin:global_stop (2x)
  • ovos.session.update_default (2x)
  • ovos.utterance.handled (15x)
  • ovos.utterance.speak (2x)

📤 Emitters:

  • mycroft.audio.play_sound (Asserted ✅)
  • ovos.intent.unmatched (Asserted ✅)
  • ovos.utterance.cancelled (Asserted ✅)
  • ovos.utterance.handle (Asserted ✅)
  • ovos.utterance.handled (Asserted ✅)
  • recognizer_loop:utterance (Asserted ✅)

ovos-skill-count.openvoiceos

⚠️ Uncovered Listeners:

  • ovos-skill-count.openvoiceos:count_to_n (Intent)
  • question:action (Intent)
  • question:action.ovos-skill-count.openvoiceos (Intent)
  • question:query (Intent)
  • homescreen.metadata.get
  • mycroft.ovos-skill-count.openvoiceos.all_loaded
  • mycroft.ovos-skill-count.openvoiceos.is_alive
  • mycroft.ovos-skill-count.openvoiceos.is_ready
  • mycroft.skill.disable_intent
  • mycroft.skill.enable_intent
  • mycroft.skill.remove_cross_context
  • mycroft.skill.set_cross_context
  • mycroft.skills.settings.changed
  • ovos-skill-count.openvoiceos.converse.get_response
  • ovos-skill-count.openvoiceos.set
  • ovos.common_query.ping
  • ovos.skills.settings_changed
    ✅ Covered Listeners:
  • mycroft.stop (1x)
  • ovos-skill-count.openvoiceos.stop (1x)
  • ovos-skill-count.openvoiceos.stop.ping (1x)

ovos-skill-hello-world.openvoiceos

⚠️ Uncovered Listeners:

  • ovos-skill-hello-world.openvoiceos:Greetings (Intent)
  • ovos-skill-hello-world.openvoiceos:HowAreYou (Intent)
  • ovos-skill-hello-world.openvoiceos:ThankYouIntent (Intent)
  • question:action (Intent)
  • question:action.ovos-skill-hello-world.openvoiceos (Intent)
  • question:query (Intent)
  • hello.world
  • homescreen.metadata.get
  • mycroft.ovos-skill-hello-world.openvoiceos.all_loaded
  • mycroft.ovos-skill-hello-world.openvoiceos.is_alive
  • mycroft.ovos-skill-hello-world.openvoiceos.is_ready
  • mycroft.skill.disable_intent
  • mycroft.skill.enable_intent
  • mycroft.skill.remove_cross_context
  • mycroft.skill.set_cross_context
  • mycroft.skills.settings.changed
  • ovos-skill-hello-world.openvoiceos.converse.get_response
  • ovos-skill-hello-world.openvoiceos.set
  • ovos-skill-hello-world.openvoiceos.stop
  • ovos-skill-hello-world.openvoiceos.stop.ping
  • ovos.common_query.ping
  • ovos.skills.settings_changed
    ✅ Covered Listeners:
  • mycroft.stop (1x)
  • ovos-skill-hello-world.openvoiceos:HelloWorldIntent (2x)

📤 Emitters:

  • mycroft.skill.handler.complete (Asserted ✅)
  • mycroft.skill.handler.start (Asserted ✅)
  • ovos-skill-hello-world.openvoiceos.activate (Asserted ✅)
  • ovos-skill-hello-world.openvoiceos:HelloWorldIntent (Asserted ✅)
  • ovos.intent.handler.complete (Asserted ✅)
  • ovos.intent.handler.start (Asserted ✅)
  • ovos.intent.matched (Asserted ✅)
  • ovos.utterance.handled (Asserted ✅)
  • ovos.utterance.speak (Asserted ✅)

ovos-stop-pipeline-plugin

📤 Emitters:

  • ovos-stop-pipeline-plugin:global_stop (Asserted ✅)
  • ovos.stop (Asserted ✅)
  • ovos.utterance.handled (Asserted ✅)

stop.openvoiceos

📤 Emitters:

  • mycroft.skill.handler.complete (Asserted ✅)
  • mycroft.skill.handler.start (Asserted ✅)
  • mycroft.stop (Asserted ✅)
  • ovos-skill-count.openvoiceos.stop (Asserted ✅)
  • stop.openvoiceos.activate (Asserted ✅)
  • stop:global (Asserted ✅)
  • stop:skill (Asserted ✅)

type

⚠️ Uncovered Listeners:

  • recognizer_loop:record_begin (Intent)
  • recognizer_loop:record_end (Intent)
    ✅ Covered Listeners:
  • recognizer_loop:audio_output_end (3x)
  • recognizer_loop:audio_output_start (2x)

⚖️ License Check

Checking if the licenses are compatible with OVOS. 🧩

❌ License violations detected — review required before merging.

Dependency                          License Name                                            License Type         Misc                                    
bidict:0.24.1                       MPL-2.0                                                 WeakCopyleft                                                 

License Type                        Found                                                  
WeakCopyleft                        1

Policy: Apache 2.0 (universal donor). StrongCopyleft / NetworkCopyleft / WeakCopyleft / Other / Error categories fail. MPL allowed.


The pulse of the OpenVoiceOS codebase 💓

JarbasAl added a commit that referenced this pull request Aug 13, 2026
@JarbasAl
JarbasAl force-pushed the fix/session-pipeline-blacklist-normalization branch from 154e9e5 to 73af2eb Compare August 31, 2026 14:09
@github-actions github-actions Bot added fix and removed fix labels Aug 31, 2026
@JarbasAl
JarbasAl force-pushed the fix/session-pipeline-blacklist-normalization branch from 73af2eb to 5485141 Compare August 31, 2026 15:51
session.blacklisted_pipelines is compared against session.pipeline as
literal strings, but the deployment blacklist is naturally expressed in
installed plugin IDs (e.g. "ovos-adapt-pipeline-plugin") while a session
pipeline carries confidence-suffixed matcher IDs (e.g.
"ovos-adapt-pipeline-plugin-high"). A base plugin policy ID silently
failed to block its suffixed matcher variants.

Per OVOS-PIPELINE-1 §3/§5.2 a blacklist entry names the plugin (the
single actor), never a matcher variant of it: a plugin cannot be denied
in one tier and invoked in another. A confidence-suffixed blacklist
entry, legacy or canonical spelling, previously only blocked that one
tier of the plugin, leaving its other tiers invokable.

Normalize both the blacklist entries and the matcher id being checked
through _PIPELINE_MIGRATION_MAP and strip the confidence suffix
(_PIPELINE_RE) down to a bare plugin id before comparing, so a
blacklisted plugin id -- suffixed or bare, legacy or canonical -- blocks
every one of its matcher variants, filtered before matcher lookup (no
invocation, no bus event for the skip).

Split out of ovos-core#808 per review -- unrelated to that PR's fallback
ping/pong migration-window fix.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@JarbasAl
JarbasAl force-pushed the fix/session-pipeline-blacklist-normalization branch from 5485141 to a6ae7fb Compare August 31, 2026 16:27
@JarbasAl
JarbasAl marked this pull request as ready for review August 31, 2026 16:34
@JarbasAl
JarbasAl merged commit 3cc33ff into dev Aug 31, 2026
16 of 18 checks passed
@JarbasAl
JarbasAl deleted the fix/session-pipeline-blacklist-normalization branch August 31, 2026 16:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant