ovos-routing-judge
Who took an utterance, and was it the skill that should have?
One judge for every tool that replays golden utterances
(test/end2end/golden_utterances_<lang>.jsonl) against
OpenVoiceOS and asks whether each sentence reached
the right skill. It is pure Python over the bus messages of one session:
no messagebus connection, no UI, no store knowledge, no dependencies. So the
same row gets the same verdict wherever it runs:
- ovos-klondike-mercantile's CI, on an in-process MiniCroft;
- ovos-tui-client's test runs
(
ovos-tui --run), on a live device over the messagebus.
A failure in CI can then be reproduced on a device and judged the same way (andlo/ovos-klondike-mercantile#48).
Use
from ovos_routing_judge import Claim, in_session, judge
claim = Claim.from_messages(recorded, known_ids=loaded_skill_ids, # Message objects or dicts
session_id=row_session_id)
v = judge(claim, own_ids={"ovos-skill-date-time.openvoiceos"},
expected="ovos-skill-date-time.openvoiceos:what_time_is_it",
hung=timed_out, known_ids=loaded_skill_ids)
v.kind # hit | wrong_intent | captured | other | unhandled | hang
v.taker # who took it
v.via # its best signal: intent | provider | ocp | skill | speak
v.detail # one line on what happened
Claim.observe(message, known_ids) folds messages in one at a time, for a
live run that wants to know as soon as something matched.
known_ids is a filter by default: only loaded skills can take a row, so a
pipeline plugin's own intent with nothing behind it is unhandled. A caller
whose skill list may be incomplete (a live device with skills in other
containers) passes strict_known=False: known skills still win, anyone else
is the fallback.
Verdicts
| kind | meaning |
|---|---|
hit |
the row's skill took it (with the expected intent, when the row names one) |
wrong_intent |
the row's skill took it, and another of its intents is what fired (no visible intent at all is a hit) |
captured |
the row's skill was waiting for an answer (get_response / converse) and took the sentence as that answer |
other |
another skill took it (taker); a store can split this further |
unhandled |
nobody took it, or only a pipeline stage with no skill behind it |
hang |
nobody took it and the caller timed out |
What counts as taking a sentence
Signals come in tiers; the taker is the first known skill in the best tier:
- intent:
<skill_id>:<intent>dispatched,ovos.intent.matched, or a pending<skill_id>.converse.*capturing it - provider: a pipeline plugin asked it for content
(
ovos.common_reading.fetch_content.<skill_id>) - ocp: OCP picked its result (
ovos.common_play.playmedia, or the first track ofplay/search.populatewithout a player) - skill: handler start, a fallback that answered, common query's
question:action - speak: it spoke in this session (
speakor core 3'sovos.utterance.speak)
ovos.intent.unmatched means nobody, whatever else was seen.
With session_id, other sessions' messages are ignored, and a message
without a session can show an intent, a provider or an OCP pick but never a
tier 4 or 5 claim: unrelated skills' background activity (a scheduled
event's handler, a fallback probe's reply) arrives without a session and is
not theft (learned in ovos-test-harness's fleet suite).
Intent names are compared in one spelling: Name.intent (ovos-workshop 1.x)
vs Name, CamelCase in older releases vs snake_case, padatious
what.time.is.it vs padacioso what_time_is_it. A row with
"intent_type": "ocp" must go through OCP.
The contract
tests/fixtures/cases.json holds recorded message sequences and the verdict
each must get. When a core changes its signals, a case goes in there and every
tool using the package gets the fix.
License
Apache-2.0
Metadata
Release files for ovos-routing-judge 0.0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ovos_routing_judge-0.0.3.tar.gz | 15.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ovos_routing_judge-0.0.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 30.9 kB
Release files / ovos_routing_judge-0.0.3.tar.gz
| Download URL | ovos_routing_judge-0.0.3.tar.gz |
|---|---|
| Size | 15.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d1dac9d7fa81aeb6bc3be3e2a9441566f1111017b2ed3b8fc1bd52cb67f9a219
|
|
BLAKE2b-256 checksum How to use checksums |
adde8116a48968906ea2bfa4db632e6e3f273c41af5b81f810d8330f8de78dee
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency logRelease files / ovos_routing_judge-0.0.3-py3-none-any.whl
| Download URL | ovos_routing_judge-0.0.3-py3-none-any.whl |
|---|---|
| Size | 15.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e94953998a593991108c65f64a6976c931c28fd05b2883e111538d2de2fa655c
|
|
BLAKE2b-256 checksum How to use checksums |
9a25483286b2ce7b51ca73db5937959c7f9c53212a3768b48d74cb5abf3ebea5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency log