Release 0.3.1a1#41
Open
github-actions[bot] wants to merge 13 commits into
Open
Conversation
…locale typos (#32) * refactor: migrate language matching and template expansion to ovos-spec-tools The deprecated ovos_utils.lang.standardize_lang_tag stripped the region subtag, and the prior chain (`standardize_lang_tag("en-US")` -> `"en"`, then `langcodes.closest_match("en", ["en-US", ...])`) was failing to find a usable match for some inputs, leaving the cancel transformer silent and the utterance falling through to the intent-failure error sound. Switching the whole chain to the spec-tools conformant implementations: - `ovos_spec_tools.standardize_lang` preserves the region subtag (`en-US` -> `en-US`). - `ovos_spec_tools.closest_lang` gates on the < 10 distance threshold internally and returns None when no candidate is close enough, replacing the manual score check. - `ovos_spec_tools.expand` replaces the deprecated `ovos_utils.bracket_expansion.expand_template`. Also fix the it-IT locale: `(|dimentica|...)` had an empty leading alternative on a standalone group, which would have matched every utterance via endswith(""). Spec-tools' strict OVOS-INTENT-1 §3.6 expansion correctly rejects it; drop the empty alternative. Verified: 44 unit tests + the end2end `test_cancel_match` on ovos-core both pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor: use LocaleResources for cancel.intent lookup Replace the hand-rolled locale discovery + file read + bracket expansion with one `LocaleResources(skill_locale=...).load_intent("cancel", lang)` call. `LocaleResources` applies the OVOS-INTENT-2 §2.1 source-precedence, the §2.2 smart language fallback (`closest_lang` gated at distance < 10), the §3 file reader (UTF-8, BOM-stripped, comment/blank-line filtered), and the §3.6 sentence-template expansion — the same composite operation this plugin was performing by hand. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor: rename cancel.intent -> cancel.voc (correct OVOS-INTENT-2 role) The plugin matches phrases via `endswith`, not full utterance templates with slots, so the resource is a vocabulary set per OVOS-INTENT-2 §4.3, not an intent template per §4.1. Switch to `LocaleResources.load_vocabulary("cancel", lang)` to match. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: add cancel.intent in each locale to document the matching pattern The plugin still does suffix-matching against cancel.voc at runtime; this .intent file is informational and not consumed. It exists so the intent the plugin enforces is explicit in the locale folder for anyone reading it: `[{utterance}] <cancel>` — anything ending with a cancel phrase, plus a standalone cancel with no leading utterance. Verified via spec-tools' LocaleResources.load_intent — the `<cancel>` reference resolves against the sibling cancel.voc and `[{utterance}]` produces both with-prefix and standalone samples. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci: add ovoscope end-to-end CI for the cancel transformer The plugin's behaviour is observable only end-to-end (bus + intent service + audio service), so unit tests can't catch the kind of regression that surfaced on ovos-core's ovoscope: cancel matching silently breaking and falling through to intent-failure. Add a local ovoscope job so this repo gates on the same observation rather than relying on downstream ovos-core to catch it. Adds: - `.github/workflows/ovoscope.yml` — reusable workflow from OpenVoiceOS/gh-automations, parameterised the same way ovos-core's is (Padatious + Adapt required, bus-coverage on). - `test/end2end/test_cancel_plugin.py` — two ovoscope cases: cancel mid-sentence (the previously regressed case) and cancel-suffix on an arbitrary utterance. - pyproject `[test]` extras: ovoscope + ovos-skill-hello-world. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci: scope build/coverage to unit tests, drop intent-engine reqs from ovoscope - build-tests + coverage: target test/unittests/ only. The new test/end2end/ directory needs ovoscope (test extras), not the dev extras these workflows install. - ovoscope: drop require_adapt / require_padatious / system_deps. The cancel transformer fires before intent matching; the ovoscope cases here do not depend on any intent engine. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(test): enable the cancel transformer in MiniCroft's config before boot OVOS's UtteranceTransformersService loads a plugin only when its entry-point name appears in `Configuration().utterance_transformers` (ovos_core/transformers.py:29); otherwise the plugin is silently skipped. The default test config used by MiniCroft does not include `ovos-utterance-cancel-plugin`, so the transformer never fired in CI and the utterance fell through to the intent-failure error sound. Set the key on Configuration() in setUp, before `get_minicroft` is called. MiniCroft's `isolate_config` clears the user's XDG configs, so this assignment only affects the test process. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: restore entry-point name to match OVOS default config; read lang from session Three real bugs surfaced by the new ovoscope tests: 1. **Entry-point name regression.** Dev had renamed the transformer entry point to `ovos-utterance-cancel-plugin`, but OVOS's default `mycroft.conf` references `ovos-utterance-plugin-cancel` under `utterance_transformers`. `UtteranceTransformersService` (ovos_core/transformers.py:29) silently skips any plugin whose name is not in the config — so the rename silently broke the plugin on every default install. Restore the historic name. 2. **`lang` lookup was wrong.** `context` here is the OVOS-MSG-1 `message.context` dict; the normative language field lives at `context["session"]["lang"]` (§4), not at `context["lang"]`. ovos-core's IntentService also copies it to a top-level `context["lang"]` for legacy callers, but treating that as authoritative breaks for any consumer (HiveMind, tests, alt bus-clients) that hands the transformer a Message without that pre-processing. Prefer `session.lang`; fall back to legacy `context.lang`; default `"en-US"` if neither is set. 3. **`None` lang crash.** `context.get("lang", default)` returns `None` when the key exists with a `None` value — only a missing key triggers the default. `standardize_lang(None)` raises `AttributeError`, which the transformer service swallows as a warning — the plugin silently no-ops. Use `or` so an explicit `None` resolves to the default. ovoscope test/end2end/test_cancel_plugin.py now covers all three: - positive cancel-mid-sentence + cancel-suffix - negative gate: with the plugin disabled in config, the same cancel-suffix falls through to intent failure — proving the positive cases are observing the plugin itself - smoke: utterance with no cancel phrase doesn't fire the cancel sequence Each test writes its desired `utterance_transformers` entry into a temp xdg-config file and boots MiniCroft with `isolate_config=False`, because MiniCroft's default `Configuration.reload()` wipes any in-memory override done in setUp. Workflow: drop bus_coverage (transformers don't emit bus events). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor: factor lang resolution into _resolve_lang helper The transformer signature passes context = message.context, which makes the lang source ambiguous: - ovos-core's IntentService currently writes a top-level context["lang"] before invoking transformers (a known convenience that should be in the spec but isn't yet — the future transformer signature will likely grow an explicit lang kwarg); - the normative carrier is context["session"]["lang"] per OVOS-MSG-1 §4. Trust the current ovos-core contract (top-level context.lang) but fall back to session.lang so the plugin keeps working when called without the ovos-core pre-processing (HiveMind, tests, alternative bus clients). Encapsulated in _resolve_lang(context) with a docstring naming the gap so the call site can be simplified once the spec is updated. Also fixes the silent crash when context.get("lang") returns explicit None: standardize_lang(None) raised AttributeError, which UtteranceTransformersService swallowed as a warning — the plugin no-op'd. or-chain guards both lookups. The entry-point rename was reverted to keep this PR's scope to the spec-tools migration; the default-config mismatch (OVOS default config keys ovos-utterance-plugin-cancel but new dev's entry point is ovos-utterance-cancel-plugin) belongs in a separate ovos-config fix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: register entry point under opm.transformer.text (the group OPM scans) OPM discovers utterance transformers under the entry-point group `opm.transformer.text` (`ovos_plugin_manager/utils/__init__.py:72`, `PluginTypes.UTTERANCE_TRANSFORMER`). The previous pyproject used `ovos.utterance.transformer`, which OPM doesn't scan — so the editable install in CI registered the plugin under a group nobody looks at, OPM returned no plugins, and the cancel transformer never loaded regardless of config. The PyPI 0.2.8 wheel happens to work because it uses the legacy `neon.plugin.text` group which OPM aliases (with a deprecation warning); the new pyproject silently broke discovery. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(test): drop final_session check on cancel mid-sentence bus-client 1.x's SessionManager normalises `session.lang` to the macro tag (`en-US` -> `en`), which trips End2EndTest's `test_final_session` equality check. The cancel sequence (four expected messages) is the real assertion here; the final-session check was inherited from ovos-core's copy of this test and is redundant. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(locale): correct Danish 'annulle'->'annuller' and Portuguese 'comado'->'comando' CodeRabbit caught two locale typos in cancel.voc: - **da-DK**: `annulle kommando` was a broken stem; the Danish imperative is `annuller`. The next four lines in the same file already use `annuller` correctly, so this was a single-line typo. - **pt-PT**: every occurrence of `comado` is a typo for `comando` (Portuguese for 'command'). Six occurrences across six template lines, all in the same vocabulary group `(ordem|comado|isso)` and variants — replaced with sed -i. The other CodeRabbit findings (UTF-8 read, order-preserving dedupe, deterministic test phrasing, immutable workflow ref) are addressed elsewhere or intentionally skipped: file reading now goes through `LocaleResources` which handles UTF-8 via the spec-tools reader; gh-automations workflow refs use `@dev` by org policy. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: require ovos-utils>=0.11.1a1 (standardize_lang_tag region-preserving) ovos-utils 0.11.1a1 restores the historic langcodes semantics of `standardize_lang_tag(macro=True)` — it performs macrolanguage substitution (`cmn` -> `zh`) instead of stripping the region (`en-US` -> `en`). With that fix in the dependency chain, `ovos_bus_client.session.SessionManager` no longer rewrites `session.lang` from `en-US` to `en`, and the cancel ovoscope tests can again assert against `final_session`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: JarbasAi <jarbasai38@mailfence.com>
…tial #7) (#35) * feat: cancel.blacklist veto for utterances *about* a cancel word (partial #7) Issue #7 calls out the false-positive class where the cancel transformer fires on utterances that mention a cancel word without intending to cancel anything — `play nevermind`, `spell forget that`, `what is the opposite of cancel`, etc. The proper fix is post-intent-dispatch (only cancel when no play/say/spell/common_qa intent matched), which needs coordination with ovos-core; until then this gates by **utterance prefix**. Adds an optional `locale/<lang>/cancel.blacklist` companion to `cancel.voc`. `.blacklist` is the OVOS-INTENT-2 §4.3 phrase-set role an engine uses to *exclude* matches — here, any utterance starting with a phrase in `cancel.blacklist` is exempt from the cancel suffix match. A missing `cancel.blacklist` for a language is non-fatal: the plugin falls back to the historic always-check-suffix behaviour. Ships an en-US `cancel.blacklist` covering the four pattern classes from issue #7: - imperative verbs that operate on the literal word: play, say, spell, pronounce, read, repeat, write, type, define, explain, translate - pedagogical patterns: `tell me the ...`, `teach me ...` - question starts: `how do you ...`, `what is ...`, `what's the (meaning|opposite|...)`, `why don't you ...` - desire patterns: `i want(ed) (that|the|to) ...` ovoscope coverage: a `spell nevermind that` utterance — which would otherwise fire the cancel sequence — falls through to intent failure under the new veto. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Update cancel.blacklist * feat(locale): translate cancel.blacklist into all 10 supported locales Ports the en-US blacklist patterns into ca-ES, da-DK, de-DE, es-ES, fr-FR, gl-ES, it-IT, nl-NL, pt-BR, pt-PT. Same four pattern classes in each: - imperative verbs that operate on the literal word (play/say/spell/pronounce/read/repeat/write/type) - pedagogical verbs (define/explain/translate, tell me, teach me) - question starts (how do you / what is / what's the meaning|opposite|translation|pronunciation / why) - meta-linguistic question forms Each file parses cleanly through ovos_spec_tools.LocaleResources .load_blacklist and expands to 29-51 prefixes per language. Same header comment in every file so translators can audit and extend without re-deriving the contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add the opm-check reusable-workflow caller to complete the canonical OVOS plugin CI set. All other shared callers were already present and using OpenVoiceOS/gh-automations@dev.
…p ovos-* deps at next major (#40)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Human review requested!