refactor: register canonical intent topics; compat moves to ovos-spec-tools - #500
refactor: register canonical intent topics; compat moves to ovos-spec-tools#500JarbasAl wants to merge 5 commits into
Conversation
The dispatch topic is `<skill_id>:<intent_name>` (OVOS-MSG-1 §2.1.1). The `.intent` extension is an authoring resource detail (OVOS-INTENT-2 §3), so it must not reach the wire. `register_intent_file` now derives the name with `canonical_intent_topic` and binds one event, the canonical one. The dual add_event/remove_event on the suffixed twin is gone; `disable_intent` / `enable_intent` / `register_intent_layer` canonicalize the author-supplied name. Old containerized skills still listen on the suffixed topic. That compat now lives in ovos-spec-tools (`intent_topics`), gated by `emit_legacy` at the bus layer, and no longer in the skill layer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 37 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
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. Comment |
Beep! I'm back with the goodies! 🍭I've aggregated the results of the automated checks for this PR below. 🔍 LintThe latest check report is officially filed. 📁 ❌ ruff: issues found — see job log 📋 Repo HealthYour repository is in great shape! ✅ ✅ All required files present. Latest Version: ✅ 🔨 Build TestsThe build process has successfully terminated. 🏁 ✅ All versions pass
🔒 Security (pip-audit)Checking for any digital cooties in your dependencies... 👾 ✅ No known vulnerabilities found (74 packages scanned). ⚖️ License CheckEnsuring our CLA requirements are met. 🖋️ ✅ No license violations found. Policy: Apache 2.0 (universal donor). StrongCopyleft / NetworkCopyleft / WeakCopyleft / Other / Error categories fail. MPL allowed. A robot's work is never done... but this PR check is! ⚙️ |
Relocated from ovoscope#127 (TestRegistrationNormalizationDedup) at the maintainer's request: ovoscope is the harness library, not the stack, and these guards belong next to the code they pin. A legacy `X:Y.intent`-registered handler must still fire exactly once on a canonical `X:Y` dispatch, and registering both spellings for one intent must collapse to a single fire, not double-dispatch. Uses ovos_spec_tools.intent_topics.IntentAliasRegistry (the real alias-collapse API — the ovoscope draft referenced a nonexistent ovos_spec_tools.intent_compat.normalize_intent_registration). Both pass outright since #500 already registers canonical-only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1.6.0a1 is released; a bare >=1.6.0 floor cannot resolve an alpha. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The alias registry is gone from ovos-spec-tools. The two guards assert the same behavior with the pure helper the registry wrapped.
spec-tools#92 (registry removal) merged and released as 1.6.0a2; pin to the simplified intent_topics surface. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Why
OVOS-MSG-1 §2.1.1 assembles the per-intent dispatch topic from named
identifiers at runtime:
<skill_id>:<intent_name>. The intent name is theskill author's label for the intent. OVOS-INTENT-1 keeps a clean line between
authoring form and wire form —
.intentis a locale resource fileextension (OVOS-INTENT-2 §3), an authoring detail. It has no business on the
bus.
Workshop built the topic straight from the resource filename, so a skill with
a
food.order.intentresource ended up on<skill_id>:food.order.intent, andregister_intent_filethen bound the handler to both spellings whilepipelines migrated. That leaves the same compat rule reimplemented in three
places in workshop and keeps the legacy identity alive in the skill layer,
where it does not belong.
This PR makes workshop spec-pure: it produces and consumes canonical topics
only. The wire-level compat that containerized old skills still need moves to
ovos-spec-tools, which now owns the whole canonical↔legacy surface.What changed
register_intent_filederives the intent name withcanonical_intent_topic(), so the registration payload and the dispatchtopic both carry
<skill_id>:food.order.add_eventon the suffixed twin is gone. One binding, thecanonical one.
disable_intent/enable_intentcanonicalize the author-supplied namebefore hitting the registry, so a skill may still say
self.disable_intent("food.order.intent"). The pairedremove_eventon thesuffixed twin is gone with the dual binding.
register_intent_layercanonicalizes string intent names the same way.IntentServiceInterface._clean_padatious_namekeeps its suffix strip butreuses the
INTENT_FILE_SUFFIXconstant from spec-tools. It now only firesfor the deprecated
register_padatious_intentAPI — the modern path alreadypasses a canonical name.
No compat code is left in workshop.
Old containers still work
A skill container running an old workshop subscribes to the suffixed topic
over the real bus.
ovos_spec_tools.intent_topicscovers it at the bus layer:IntentAliasRegistryrecords that an old consumer registered the suffixedspelling, and
legacy_reemit_targets— gated by the existingemit_legacyconvention — mirrors the canonical dispatch onto the suffixed twin for exactly
those intents. Alias-driven by default, so no topic is invented.
Depends on
Pairs with OpenVoiceOS/ovos-spec-tools#88, which adds
canonical_intent_topicand the compat helpers. That PR must merge andrelease before this one: the floor here is bumped to
ovos-spec-tools>=1.6.0and CI stays red until that release exists. No gitref is pinned in
pyproject.toml— a direct URL there breaks the PyPIpublish.
Tests
test/unittests/skills/test_base.py, rewritten around the spec-purebehaviour:
time.intentresource registers<skill_id>:timewith the intent service;<skill_id>:….intenttopic is emitted or bound by workshop duringregistration (the "spec-pure" guard);
disable_intent("time.intent")still works and queries the registry by thecanonical name.
test/unittests/test_skill.pyandtest/unittests/test_decorators.pyareupdated for the canonical names they now see on the wire.
Run with the spec-tools branch on
PYTHONPATH:test_base.py74 passed;test_skill.py+test_decorators.py37 passed;test_intent4_producer.py,test_intent4_adversarial.py,test_intent_service_interface.py,test_malformed_template_resilience.py,test_inline_vocab_refs.py55 passed.skills/test_intent_layers_e2e.pyerrors in setup both with and without thisbranch — the demo skill does not load in a worktree checkout. Pre-existing,
unrelated.
Maintainer-approved design. Implemented by Claude (opus), orchestrated by
Claude Fable.
🤖 Generated with Claude Code