Skip to content

OVOS-COMMON-QUERY-1: Common Query Pipeline Plugin Specification#40

Draft
JarbasAl wants to merge 13 commits into
devfrom
spec/common-query
Draft

OVOS-COMMON-QUERY-1: Common Query Pipeline Plugin Specification#40
JarbasAl wants to merge 13 commits into
devfrom
spec/common-query

Conversation

@JarbasAl
Copy link
Copy Markdown
Member

@JarbasAl JarbasAl commented May 28, 2026

Companion issue: #41

Summary

Defines the common query pipeline plugin — a scatter-gather matcher that identifies question-like utterances, broadcasts them to registered question-answering skills, collects responses within a timed window, selects the best answer by confidence, and dispatches the winning skill to speak it.

What the spec covers

  • §3 — Plugin role (pure-matcher; Match.skill_id is the winning skill, never the plugin's own pipeline_id)
  • §4 — Question gate: binary accept/reject pre-filter before broadcast
  • §5 — Scatter-gather cycle: ovos.common_query.question broadcast, timed collection window, early termination, searching extension protocol
  • §6 — Skill-side question protocol: response shape with confidence score and answer-type metadata
  • §7 — Dispatch and Match construction: <winning_skill_id>:common_query.question
  • §8 — Answer-type metadata (advisory COSC labels)
  • §9 — Discovery: ovos.common_query.ping / ovos.common_query.pong
  • §11 — Pipeline positioning (after deterministic intents, before persona and fallback)
  • §13 — Conformance

Key design decisions

  • common_query.question is a skill-owned intent name, not a reserved name — skills register it via INTENT-4 and receive dispatch normally
  • Session blacklisting applies: session.blacklisted_skills excludes skills from the scatter-gather pool
  • Discovery follows PIPELINE-1 §10 pattern

Defines the scatter-gather question-answering pipeline plugin:
question gate (§4), scatter-gather cycle (§5), skill-side protocol
(§6), dispatch and Match construction (§7), answer-type metadata
(§8), discovery protocol (§9), relation to intent classification
(§10), pipeline positioning (§11), bus surface summary (§12), and
conformance (§13).

Key design decisions:
- Pure-matcher plugin (PIPELINE-1 §7.0): Match.skill_id is the
  winning skill, not the plugin pipeline_id
- Bus topics use ovos.common_query.* namespace consistently
- Discovery via ping/pong per PIPELINE-1 §10 pattern
- Dispatch on <skill_id>:common_query.question (intent_name,
  not a reserved name)
- timed collection window with early-termination and skill-side
  extensions
- no reserved intent_names (§2)

Co-Authored-By: opencode/glm-5.1 <noreply@opencode.ai>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 067a4985-8d2d-4b30-ade9-f9f5c4e79750

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR introduces a complete specification for the OVOS common query pipeline plugin, a scatter-gather pure matcher that broadcasts questions to registered skills, collects responses, filters by confidence and denylists, and dispatches the highest-confidence skill result.

Changes

OVOS Common Query Plugin Specification

Layer / File(s) Summary
Specification foundation and core concept
README.md, common-query.md (lines 1–131)
Adds a OVOS-COMMON-QUERY-1 index entry to the architecture specification catalog and introduces the plugin's scatter-gather matcher role, normative scope, reserved intent behavior, and pure-matcher return contract.
Question gating and scatter-gather cycle
common-query.md (lines 134–315)
Specifies the question gate as a binary filter for factual questions, defines the broadcast topic and skill response formats (searching, decline, final), ordered filtering by confidence and denylists, timing and extension rules with an absolute maximum window, and early termination semantics.
Skill protocol and dispatch construction
common-query.md (lines 318–432)
Documents skill-side subscription obligations, required response emission patterns, Match construction fields (intent_name, language, utterance, session), dispatch topic shape, and optional answer-type metadata as advisory hints.
Discovery, pipeline positioning, and conformance
common-query.md (lines 434–626)
Specifies ping/pong discovery, how the plugin discovers and maintains the known-skills set, pipeline positioning and tier behavior relative to intent classification, summarizes bus surface topics and MUST/SHOULD conformance obligations for both the plugin and participating skills, and lists related specifications.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Possibly related issues

Possibly related PRs

  • OpenVoiceOS/architecture#14: Both PRs document the pipeline plugin contract and pattern; the referenced PR establishes the general pipeline-plugin architectural model while this PR specifies a concrete implementation (common query) conforming to that model.

Poem

🐰 A scatter of queries flies far and wide,
Skills respond with confidence as their guide,
The fairest answer wins the race,
Pure matching finds its rightful place. 🎯

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately summarizes the primary change: adding a specification document for the OVOS Common Query Pipeline Plugin, which matches the main content of both files changed (README.md reference addition and the full specification in common-query.md).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch spec/common-query

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@common-query.md`:
- Around line 512-525: The fenced code block showing the session.pipeline array
lacks a language tag and triggers MD040; update the block by adding an
appropriate language identifier (e.g., yaml) to the opening fence so the block
containing session.pipeline and entries like "stop_high", "converse",
"template_high", "keyword_high", "common_query", "template_medium",
"keyword_medium", "fallback_medium", and "fallback_low" is labeled (for example
```yaml) to satisfy markdown linting and CI.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d0b9398a-e73f-4b3d-a606-d9d661489915

📥 Commits

Reviewing files that changed from the base of the PR and between cec6c7d and 88ba4a5.

📒 Files selected for processing (2)
  • README.md
  • common-query.md

Comment thread common-query.md
Comment on lines +512 to +525
```
session.pipeline: [
"stop_high", # interrupt
"converse", # active-handler poll
"template_high", # registered intents (high)
"keyword_high", # registered intents (high)
"common_query", # scatter-gather question answering
"template_medium",
"keyword_medium",
...
"fallback_medium",
"fallback_low"
]
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a language to the fenced code block to satisfy markdown linting.

Line 512 uses an unlabeled fenced block, which triggers MD040 and may fail docs CI.

Proposed fix
-```
+```yaml
 session.pipeline: [
   "stop_high",           # interrupt
   "converse",            # active-handler poll
   "template_high",       # registered intents (high)
   "keyword_high",        # registered intents (high)
   "common_query",        # scatter-gather question answering
   "template_medium",
   "keyword_medium",
   ...
   "fallback_medium",
   "fallback_low"
 ]
</details>

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.22.1)</summary>

[warning] 512-512: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @common-query.md around lines 512 - 525, The fenced code block showing the
session.pipeline array lacks a language tag and triggers MD040; update the block
by adding an appropriate language identifier (e.g., yaml) to the opening fence
so the block containing session.pipeline and entries like "stop_high",
"converse", "template_high", "keyword_high", "common_query", "template_medium",
"keyword_medium", "fallback_medium", and "fallback_low" is labeled (for example

@JarbasAl JarbasAl marked this pull request as draft May 28, 2026 02:17
JarbasAl and others added 3 commits May 28, 2026 05:29
…ADME)

New-spec metadata per AGENTS.md §2.1 exception: a new spec MAY
combine its normative file with the metadata sweep.

Additions:
- appendix/rationale.md §4.9: bridge design rationale (minimalism,
  client isolation, session_id as MAY convenience, layer-2 injection,
  hardened-set trade-off)
- appendix/divergences.md §5.8: HiveMind comparison (session_id vs
  destination-based routing) and conformance note
- appendix/gaps.md: bridge-specific gaps (multi-hop cascade, wire
  format, health/heartbeat)
- README.md: OVOS-BRIDGE-1 row in orchestrator stack table
- rename `phrase` → `utterance` for consistency with PIPELINE-1 vocabulary
- remove `lang` from all data payloads; language read from context.session.lang
- remove `handles_speech` field and §6.1 (framework internal, not bus contract)
- remove §8 answer-type metadata (defined nothing normative; reduces to one
  sentence in §4.1 about advisory hint fields)
- move §10 "relation to intent classification" out of normative body
- fix conf bug: `conf` is now conditional-required when `answer` is present;
  drop the "missing conf treated as 0" silent-discard rule
- fix timing contradiction: separate initial window (RECOMMENDED 3s) from
  maximum window (RECOMMENDED 5s) so extensions have actual headroom
- fix selection: drop reranker/ignore_skill_scores implementation detail;
  selection is "highest conf, deployer-defined tie-break"
- add MUST NOT session mutation in §6.1 (common query is stateless)
- add edge case: skill that sends only searching:true with no final response
  before max window is treated as decline
- add edge case: duplicate final responses — first wins
- fold §2 "reserved intent_name" into §2 intro paragraph
- merge §5.5 "empty skill set" into §4.4 timing
- fix ToC: sections now correctly list §2–§10
- conformance updated throughout; remove callback_data from skill MUST,
  remove reranker from plugin SHOULD

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@JarbasAl JarbasAl changed the title COMMON-QUERY-1: common query pipeline plugin specification OVOS-COMMON-QUERY-1: Common Query Pipeline Plugin Specification May 28, 2026
JarbasAl and others added 6 commits May 28, 2026 09:37
…ion, conf

- Fix timing RECOMMENDEDs: initial 1s (was 3s), maximum 3s (was 5s); add
  note that voice-responsive deployments SHOULD keep initial window ≤1s
- Add §4.5 multi-session response correlation: plugin MUST key collection
  state by session_id from context.session; cross-session responses MUST
  be discarded — was completely unspecified
- Reframe §3 question gate as cost-optimisation pre-filter, not primary
  quality gate; confidence filter (§4.3) is the primary quality gate;
  gate-less deployments are explicitly conformant
- Soften gate conformance: MUST NOT accept commands → SHOULD NOT accept
  unambiguous action commands; acknowledge the question/command boundary
  is fuzzy; note that over-acceptance is recoverable, under-acceptance is not
- Add conf value range table in §4.3 (0.0–1.0 in four bands) so cross-skill
  values are interoperable
- Add reranker SHOULD in §4.3 and conformance: plugin SHOULD use a reranker
  when available to rank surviving candidates instead of raw conf ordering
- Note in §4.3 that conf is self-reported and uncalibrated across skills
- Add streaming answer delivery to "does not define" in §1
- Update conformance throughout to reflect gate-optional framing,
  session-correlation MUST, and reranker SHOULD

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…window

Fast-win threshold (§4.3 step 3):
- plugin SHOULD close the collection window immediately when any
  denylist-surviving response exceeds a deployer-defined
  fast_win_threshold (RECOMMENDED 0.9)
- listed as the second early-close condition in §4.4 alongside
  all-responded and single-skill

Adaptive initial window via latency hints (§7):
- ovos.common_query.pong gains optional latency_ms field — skill's
  expected response time in milliseconds
- plugin SHOULD set the initial window to max(latency_ms) across
  registered skills (clamped to maximum window) rather than a fixed
  constant; unknown-latency skills fall back to the fixed RECOMMENDED
- skill SHOULD include latency_ms in pong response

§4.4 early-close conditions made explicit as a numbered list:
  1. all-responded
  2. fast-win
  3. single-skill (special case of 1, made explicit)

Conformance updated throughout.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ndler

Structural redesign to align with stop/converse/fallback patterns:

- common_query is now a reserved intent_name (PIPELINE-1 §7.3 registry)
- plugin bundles its own handler; Match.skill_id = plugin's pipeline_id
- two-phase architecture:
  * match(): fast ping/pong poll ("wants_to_answer") — skills do local
    keyword/vocab checks only, MUST NOT perform network/IO during pong
  * handler (<pipeline_id>:common_query): dispatches <skill_id>:common_query
    to claiming skills in parallel, collects full answers via reply
    derivation, reranks, speaks best via ovos.utterance.speak

Previous broadcast+scatter model replaced:
- ovos.common_query.question (broadcast eval) → ovos.common_query.ping
- ovos.common_query.question.response (shared) → ovos.common_query.pong
  (reply derivation, carries can_answer + latency_ms)
- winning dispatch → <skill_id>:common_query (plugin handler → skill)
  skill responds with answer+conf via reply, MUST NOT speak

Key constraints:
- skill MUST NOT call ovos.utterance.speak; plugin handler speaks
- pong MUST be synchronous/local; no blocking I/O
- plugin MUST preserve claiming skill list between match and handler
- session keying (§5.3, §6) preserves multi-session isolation

Retained from previous version:
- question gate as optional cost-optimisation pre-filter (§4)
- fast-win threshold (§7.2 step 3)
- adaptive collection window from latency_ms (§7.3)
- conf range table (§7.2)
- reranker SHOULD (§7.2 step 4)
- pipeline positioning guidance (§9)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…iming_skills slot, handler.error

- Resolve silence vs early-termination contradiction: drop 'prior pong history'
  early-close condition; poll window closes on sufficiency or timeout only;
  'remain silent' guidance now consistent with §5.3
- Add normative pong latency bound: MUST complete within deployer-configured
  bound; RECOMMENDED 100ms
- Carry claiming skill_ids in Match.slots as claiming_skills (§6) — removes
  reliance on in-process state, safe for distributed deployments
- Specify answer response topic: <skill_id>.common_query.response (dotted form,
  reply derivation); was previously underspecified
- Clarify <skill_id>:common_query sub-dispatches: direct plugin-to-skill bus
  messages, orchestrator does not participate, skills MUST NOT emit lifecycle
  signals
- Fix §7.2 step 5: no-answer is expected outcome, not handler error; emit
  handler.complete + graceful ovos.utterance.speak response
- Merge §7.4 into §7.2 step 4 'Selection and speaking'; remove as standalone
- Remove duplicate topic table from §8; point to §10 bus surface
- Add <skill_id>.common_query.response to §10 bus surface table
- Conformance updated throughout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- §4: "emits an error" → "speaks graceful no-answer and completes normally"
  (contradicted §7.2 step 5 which reserves handler.error for crashes)
- §7.2 step 4: drop unverified PIPELINE-1 §9.6 subsection number
- §8 obligation 3: §7.4 → §7.2 step 4 (§7.4 was merged in previous commit)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…hing

Core design change: match now does everything (ping/pong + answer
collection + filtering + selection). Handler becomes trivial: read
answer from Match.slots and speak it.

When no answer survives confidence filtering, match returns None —
pipeline continues to fallback naturally. Eliminates the need for
any new PIPELINE-1 handler-lifecycle signal.

Match.slots shape extended: answer, conf, answer_skill_id,
claiming_skills.

New §5 pre-caching optimisation: plugin MAY subscribe to utterance
arrival event and begin scatter-gather in parallel with upstream
pipeline stages. Cache keyed by session_id, TTL 10s on unclaimed
entries, evicted on consumption.

§11 pipeline positioning: documents latency profile explicitly;
common_query is an inherently slow stage, should sit just before
fallback. Pre-caching amortises cost but does not change worst-case.

Bus surface updated: <skill_id>:common_query now sent during match,
not by the handler.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
JarbasAl and others added 3 commits May 28, 2026 21:04
…t correctness, slot trim

Address design-review findings:

- §2.1: name common query a deliberate exception to PIPELINE-1 §4.4
  latency discipline (the answer IS the claim decision, so collection
  cannot defer to the handler). Require match-timeout bound >= collection
  ceiling or the stage is skipped mid-contest. Cite §4.4 by section.
- §5: rename to "early-start optimisation"; subscribe to the concrete
  ovos.utterance.handle entry topic (PIPELINE-1 §9.1), not a vague event.
- §5.1: cache holds only RAW responses + utterance, never a selected
  answer; all filtering/selection runs at match time against the LIVE
  session — fixes the staleness hole where a pre-collected answer ignored
  an upstream blacklist/session change. Discard cache on lang mismatch.
- §5.2: key cache by (session_id, utterance); evict on consumption and on
  any new utterance; drop the arbitrary 10s TTL (leaked implementation).
- §6.1/§6.2/§7.1: add utterance echo as explicit correlation key on ping,
  pong, and response; discard non-correlated messages — fixes the
  race between concurrent utterances in one session.
- §6.2: reframe pong bound — plugin MUST enforce poll-window timeout,
  skills SHOULD respond within bound (was an unenforceable skill MUST).
- §6: articulate ping/pong rationale (cheap local filter gating the
  expensive full-answer path) so it is not cargo-cult.
- §7.2/§8: split MUST-support vs SHOULD-timing for early termination.
- §9: trim Match.slots to just {answer} — claiming_skills/answer_skill_id
  were dead weight the trivial handler never read.
- Move tunable defaults to Appendix A, confidence ranges to Appendix B;
  unclutters the normative body.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The gate was framed as merely optional. Make it a SHOULD: a plugin
SHOULD apply a classifier or cheap short-circuit to skip the contest
for non-question-like utterances (weather, music, timers, plain
statements). A cheap up-front reject is the largest latency win for
mixed traffic. Gate-less remains conformant — the confidence filter
guarantees correctness — but pays the broadcast cost every utterance.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ssary, changelog)

Non-normative companion content for the common query spec:

- appendix/rationale.md §4.9: why match blocks (the answer is the claim
  decision), why None-on-no-answer keeps fallback alive, why ping/pong
  is a cheap filter not ceremony, why early-start caches only raw
  responses against the live session, and the gate as the largest
  latency win on mixed traffic.
- appendix/comparisons.md §2.6: Mycroft CommonQuerySkill as the direct
  ancestor — same scatter-gather shape, but two-phase for a different
  reason (their bus-timeout management vs. our cheap-filter/expensive-
  answer split), contest in the pipeline not a skill, single plugin
  speaker. Alexa/Google resolve centrally and have no analogue.
- GLOSSARY.md: common query, scatter-gather, wants-to-answer poll.
- CHANGELOG.md: OVOS-COMMON-QUERY-1 v1 initial-draft entry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant