Each entry records a change to a specification in this repository. Each
specification carries a Version field equal to its V0/V1/V2 compatibility
class (VERSIONING.md): 1 for a formalization compatible with the pre-spec
status quo, 2 once it is not backwards compatible. Entries are grouped under
the spec's current class. Every pull request that alters normative content adds
an entry here.
- The audio output service: the rendering pipeline (dialog-transformer
chain, TTS synthesis, TTS-transformer chain, playback queue), the
sequential playback queue shared by speech (
ovos.utterance.speak) and sound effects (ovos.audio.queue/ovos.audio.play_sound), the remote-client rendering mode (ovos.utterance.speak.b64→ovos.audio.speech), output lifecycle signals (ovos.audio.output.started/.ended), the speaking-status query (ovos.audio.is_speaking), stop integration (ovos.audio.stop,ovos.stop), and thelisten-triggeredovos.mic.listenfollow-up.
- Initial draft. Defines persona as a scoped match+handler layer with
its own pipeline position,
persona_idsession field, summon and dismiss bus messages, match contract (MAY returnNonefor pass- through), handler contract, no-persona mode, multiple-persona coexistence rules,fallback_pipeline_idfor escalation, dialog- transformer compatibility, capability-discovery viaovos.persona.capabilities, and conformance roles (Persona Plugin, Orchestrator, Skill).
- Initial draft. Defines
session.intent_contextas a flat map of key → entry carried inside the SESSION-1 session carrier. Covers context entries (key, value, TTL, ownerskill_id), private vs. shared scopes (:discriminator in the key), decay (TTL counts down per utterance; entries without TTL are session-persistent), three mutation pathways (skill bus events; engine auto-population on match; orchestrator sweep on session close), therequires_contextandexcludes_contextintent declaration fields, interaction with the match result (context values MAY be injected intoMatch.slots), and conformance roles (Orchestrator, Pipeline Plugin, Skill). Non-goals: trust enforcement and replay prevention are explicitly out of scope.
- Initial draft. Defines six transformer chains at six injection
points in the OVOS-PIPELINE-1 §6 utterance lifecycle, in lifecycle
order: audio (raw audio before STT, §3.1), utterance (post-STT text
normalization before intent matching, §3.2), metadata (session
enrichment after the utterance text, before the match round, §3.3),
intent (match-result adjustment after the match round, before
dispatch, §3.4), dialog (response-text transformation after a skill
emits
speak(), before TTS, §3.5), and tts (synthesized-audio transformation after TTS, before playback, §3.6). An orchestrator MAY implement any subset of the six points; an unimplemented chain is a no-op. Chains are ordered; the output of one transformer is the input to the next. Per-session ordering and denylists via the<type>_transformers/blacklisted_<type>_transformerssession fields (§5). Defines session mutation discipline: transformers MAY mutate session fields they own (SESSION-1 §2.1) but MUST NOT mutate fields owned by other specs; and utterance cancellation (§8) as the only sanctioned early short-circuit of the lifecycle, preserving theovos.utterance.handledinvariant. Conformance roles: Audio, Utterance, Metadata, Intent, Dialog, and TTS Transformer, plus Orchestrator.
Breaking change. Version 2 adds the <name> inline vocabulary reference
token. A template using <name> is not valid version-1 syntax — a version-1
tool does not recognize the token and cannot expand the template.
- §3.7 (new) — the
<name>inline vocabulary reference: a token replaced during expansion by a named slot-free vocabulary (a.voc, OVOS-INTENT-2). - §3 —
<name>added to the grammar token table; §1 lists it under the expansion facet. - §2 —
<and>added to the structural metacharacters that cannot occur as literal input. - §4.1 — expansion gains a first step that resolves
<name>references recursively, before the[x]/()steps. - §3.6 — new malformed forms: a reference to an undefined vocabulary, and a
cyclic reference chain;
<and>join the unbalanced-metacharacter rule. - §7 — the Expander conformance role MUST resolve inline vocabulary references.
- §3.4, §3 — a named slot MAY be written either
{name}or{{name}}; the two forms are exactly equivalent, with a conformant tool folding{{name}}to{name}. The slot-name charset and whitespace rules apply to both. The double-brace spelling is a slot, not a brace-escaping form; the grammar still provides no escape. - §5.5 — slot consistency applies to
.dialogonly; a.intentfile MAY declare different slot sets across its templates, and the engine extracts the slots of the best-matching template. §6.2 — the engine verifies a consistent slot set for.dialogand accepts differing slot sets for.intent.
- Initial draft.
Breaking change. Version 2 reinterprets brace handling in .prompt and
.dialog files. A .prompt authored against version 1 changes meaning under
version 2: its {{ … }} sequences become substitution points, and its
<!-- … --> sequences are no longer stripped.
- §4.4 (
.prompt) — the substitution variable is now the double-brace{{name}}form only. A single{name}, a lone{or}, and literal JSON/markup pass through unchanged, which is why prompts (full of literal single braces) require double braces. The previous author-comment exception is removed: a.prompthas no comment handling and<!-- … -->is literal text.{{name}}substitution is now the only special handling a.promptreceives, dropping the prior fenced-code-block rule (a single-brace{name}is already literal everywhere). - §4.2 (
.dialog) — now recognizes both named-slot forms,{name}and the equivalent{{name}}, per OVOS-INTENT-1 §3.4, treating them identically. The prior "single-brace only; no{{ }}form" restriction is dropped. - §4.1 (
.intent) — clarified to match OVOS-INTENT-1 §5.5: lines MAY declare different sets of named slots, the intent's slot set is their union, and the engine extracts only the slots of the matched template. The prior "every line MUST declare the same set of slots; use a separate file" rule is dropped for.intent(it still holds for.dialog, §4.2).
- The locale folder layout and the plain-text resource file formats
(
.intent,.dialog,.entity,.voc,.blacklist). - §1, §4.3 — the
.vocrole is a named set of localized phrasings, consumed as a keyword vocabulary and/or referenced inline via<name>(OVOS-INTENT-1 §3.7), and may itself contain such references. - §4.4 — the
.promptresource role: a whole-file verbatim string delivered to a language model. Not a template grammar file: no expansion, no line filtering, every character literal. Author-only HTML-style comments (<!-- … -->) are stripped before delivery; a malformed comment (unmatched<!--) MUST be reported. Optional{name}substitution fills only names the caller provides; unfilled slots remain literal text, and slots inside fenced code blocks are never substituted. Follows the §2.1 locale-override precedence.
- The intent definition model: keyword and template intents, identity, captured slots, suppression, and the handler contract.
- §5.1 — a template intent's
.intenttemplates MAY declare different slot sets; the engine extracts the slots of the best-matching template (OVOS-INTENT-1 §5.5). - §5.3 —
required_slots: an optional list of slot names the engine MUST extract for a match to be valid; a required slot must be declared by at least one template, otherwise the definition is malformed. §5.4 (Example) and §5.5 (the.blacklistsuppression) renumber accordingly. - §7.1 — a handler MAY rely on
required_slotsbeing populated; all other slots remain optional and must be defended against.
- Initial draft. Formalizes existing OVOS bus behaviour as a single
specification covering: the on-the-wire JSON envelope (
type/data/context); the routing keyssourceanddestinationthat mark the OVOS / handler-code boundary (the attachment point layer-2 systems like HiveMind build on top of); thesessioncarrier with two normative internal fields —session_id(where"default"is reserved for "the Message originates from the device itself", already used byovos-audioto decide whether to play TTS locally; an absentsessionis treated as equivalent tosession_id: "default", andforward/reply/responseMAY materialize the default during derivation) andlang(the user's preferred language, distinct from per-payloaddata.langdescribing the message's data language, usually but not necessarily matching); theforward/reply/responseMessage derivations; the topic+session correlation model for.responsematching; and UTF-8 JSON serialization rules. No new fields are introduced; every key and derivation defined already exists in current OVOS code paths (ovos-bus-client.Messagefor the envelope,Message.replyfor source/destination swap,context["session"]for the session carrier,ovos-audiofor thesession_id == "default"policy hook). Encryption, transport, authentication, authorization, retry, delivery and ordering guarantees, session lifecycle, and the internal shape ofsessionbeyondsession_idandlangare explicitly out of scope.
- The state-ownership model (stateless bus, stateless orchestrator for
named sessions, orchestrator-owned default session), the mutation
boundaries,
ovos.session.sync(§2.7), client-side merge rules, resumption semantics, and conformance. - §2.4 — a handler that emits no Message cannot propagate in-place
session mutations: the orchestrator-emitted handler-lifecycle trio
does not reflect handler-side changes, so a handler whose mutations
must appear in terminal events emits at least one Message
(
ovos.utterance.speakorovos.session.sync).
- The
context.sessioncarrier wire shape: thesession_idandlangcore fields, the language field family (§3.2), the §2.1 field-registry mechanism by which other specifications claim OPTIONAL session fields, and the propagation and wire-weight rules. - §2.1 — registered fields and their owning specifications:
converse_handlers(OVOS-CONVERSE-1 §2.1),fallback_handlers(OVOS-FALLBACK-1 §4), andpersona_id(OVOS-PERSONA-1 §3). - §3.3 —
site_idis defined by OVOS-BRIDGE-1 §3.3; this section states the consumer constraints that apply within the orchestrator pipeline. - See also — each field's owning specification, including
session.active_handlers(OVOS-PIPELINE-1 §7.1) andsession.converse_handlers(OVOS-CONVERSE-1 §2.1).
- Bus contract for declaring intents and entities, the wire companion to
OVOS-INTENT-3. Registration topics (
ovos.intent.register.keyword/.template,ovos.entity.register), deregistration / enable / disable, and orchestrator-owned manifest introspection (ovos.intent.list/.describe). Keyword registration carries inlinerequired/optional/one_of/excludedvocabulary descriptors. A single intent MAY be registered under both keyword and template methods. Registrations are fire-and-forget broadcasts: no.responseacknowledgement; manifest presence is the only success signal. Consuming plugins log malformed-payload rejections at WARN with full identifiers and the rejecting topic. File paths never cross the bus — locale files are expanded inline before emission. - §6 —
required_slots: an optional array on theovos.intent.register.templatepayload listing slot names the engine MUST extract for a match to be valid (OVOS-INTENT-3 §5.3). §6.2 — templates MAY declare different slot sets (OVOS-INTENT-1 §5.5). §6.3 — arequired_slotsentry naming a slot no template declares is malformed. - §11 — session-scoped registration. The registration key is the quintuple
(session_id, skill_id, intent_name, lang, method), read fromcontext.session.session_id;session_id == "default"is the global scope every session inherits (§11.2). Deregistration MAY narrow to onesession_id(§8.4); session teardown removes its session-scoped registrations (§11.3). A plugin that does not implement session scoping treats every registration as global (§11.4). §11.5 — the orchestrator routes a session-scoped intent only to utterances whose session matches the registration'ssession_id. - §8.1 — intent replacement is keyed by the quintuple, entity replacement
by
(session_id, skill_id, entity_name, lang). §12 — the orchestrator keys the manifest by the quintuple and serves session-awareovos.intent.listqueries.
- §6 (new) — listening lifecycle signals. The audio input service
emits
ovos.listener.record.started/ovos.listener.record.endedaround voice-command capture, acceptsovos.listener.sleepto enter sleep mode and suspend capture, and emitsovos.listener.awokenon the sleep→awake transition. These replace the legacyrecognizer_loop:record_begin/recognizer_loop:record_end/recognizer_loop:sleep/mycroft.awokentopics. All carry no payload; the session is identified bycontext.session.session_id. - §6.5 — bus surface table for the listener role, including the
consumer-side
ovos.mic.listenrow (defined in OVOS-AUDIO-1 §4.4). - See-also — cross-references OVOS-AUDIO-1 §4.4 as the defining spec
for
ovos.mic.listen.
- Initial draft. Formalizes the Virtual Media Player: one logical, session-scoped media player that every media command targets, behind which any number of playback backends, remote devices, or external OS players may serve a track. Defines the player and media state model; the bus surface that requests playback and transport control and reports state; the distinction between playback requests (start something) and control requests (act on what is already playing); and the MPRIS bridge by which the virtual player is exported to the host OS and by which externally-initiated, standards-compliant players become controllable by voice. Media discovery and ranking, URI-to-bytes playback, stream-extraction formats, now-playing rendering, and the NLU that classifies an utterance as media are out of scope — provider, backend, GUI, and pipeline concerns respectively.
- Initial draft. Formalizes the GUI display subsystem that decouples
voice applications from rendering technology: applications declare
what to display by naming a template from a closed, curated
vocabulary of
SYSTEM_*templates and supplying that template's session data; interchangeable render backends (adapters) decide how. Defines the closed template vocabulary (§3) — state/feedback, content primitives, media, domain cards, and interactive companions — each with its normative session-data keys; the wire protocol (§4) —gui.value.set/gui.page.show, the reserved__from/__idledata keys, and the per-session namespace lifecycle; addressing (§5) — routing bysession_idalone, with shared/multi-room screens expressed by clients sharing asession_idand no separate site/location dimension; the adapter contract (§6) — entry-point discovery, unconditional multi-modal fan-out to every installed adapter, exception-safe non-blocking handlers/hooks keyed bysession_id, and capability-degradation guidance; the interaction path (§7) for media transport andconfirm/selectresponses carrying the originatingsession_id; and conformance (§8) for producers, the GUI service, and adapters. Raw-passthrough templates (SYSTEM_html/SYSTEM_url) are documented as discouraged escape hatches. Builds on OVOS-MSG-1 (envelope), OVOS-SESSION-1 (thesession_idrouting key and reserved"default"), and OVOS-SESSION-2 (lifecycle / client authority).
- The stop pipeline plugin: matches utterances expressing the intent to
interrupt the assistant and either cascades a stop across the
recency-ordered active handlers or broadcasts a global stop. The
ping/pong discovery exchange (
ovos.stop.ping/.pong, §4) that selects the most recently activated handler able to stop, per-handler dispatch on the reserved intent_namestop(<skill_id>:stop, OVOS-PIPELINE-1 §7.3), the global-stop path (global_stop→ovos.stopbroadcast), and the session-scoping obligations oversession.active_handlers.
- Initial draft. Specifies the common query pipeline plugin: a
scatter-gather contest that answers factual questions by
broadcasting the utterance, collecting competing answers from
skills, ranking them, and speaking the best. Reserves the
common_queryintent_name (PIPELINE-1 §7.3). The full contest runs in the plugin's blockingmatch(a deliberate, documented exception to PIPELINE-1 §4.4 latency discipline, since the answer is the claim decision): a fastovos.common_query.ping/pongpoll filters skills down to plausible answerers using only cheap local checks, then<skill_id>:common_queryrequests full answers (where network and DB I/O are expected) collected on<skill_id>.common_query.response. Filtering and selection (minimum confidence, denylist, fast-win, optional reranker) run against the live session; if no answer survives,matchreturnsNoneso the pipeline reaches fallback. A surviving answer is carried inMatch.slots.answerand spoken by the plugin's trivial handler — skills never speak. Defines an optional question gate (SHOULD, for latency) and an early-start optimisation subscribing toovos.utterance.handleto overlap the contest with upstream pipeline stages, caching only raw responses keyed by(session_id, utterance). All poll/answer messages carry theutteranceas correlation key and derive via MSG-1reply, with the session incontext.session. Tunable defaults and confidence-range guidance are collected in appendices.
- The fallback pipeline plugin: the final stage(s) that handle utterances
no earlier stage claimed by querying registered fallback skills in
priority order and dispatching to the first willing one. Skill
registration (
ovos.fallback.register/.deregister) with a priority hint, session-scoped per OVOS-INTENT-4 §11. Thesession.fallback_handlerspreference list (§4), pool construction (§5), the sequential unicast ping/pong match contract (<skill_id>.fallback.ping/.pong, §6), dispatch on the reserved intent_namefallback(§7, OVOS-PIPELINE-1 §7.3), and pipeline positioning with multi-stage priority ranges (§8).
- The imperative continuous-dialog surface. Two session fields:
converse_handlers(§2.1), a recency-ordered list of active handlers, andresponse_mode(§2.2), the single entry holding the next utterance exclusively. The converse plugin as a pure matcher (§3) that checksresponse_modefirst, then pollsconverse_handlersvia sequential unicast ping/pong (<skill_id>.converse.ping/.pong, §4). Response mode (§5): single-shot delivery via the reservedresponseintent_name. Activation lifecycle (§6), stop integration (§7), and the bus surface (§8). Dispatch on the reserved intent_namesconverseandresponse(OVOS-PIPELINE-1 §7.3) follows ordinary §7 routing.
- §6.2 — the orchestrator treats a
Matchas declined when any slot listed in the intent'srequired_slots(OVOS-INTENT-3 §5.3) is absent, behind the engine's own enforcement duringmatch. - §7.3 — reserve the intent_names
fallback(OVOS-FALLBACK-1 §6.3) andcommon_query(OVOS-COMMON-QUERY-1 §3). - §9.6 — the OPTIONAL
listenfield onovos.utterance.speak: whentrue, the output stage re-opens the user input channel after the response is delivered.
- The utterance lifecycle, the pipeline-plugin
matchcontract, the session fields owned by this specification (§5), dispatch (§7), the handler-lifecycle trio (§8), and the utterance-layer topics — the entry pointovos.utterance.handle(§9.1) and the response exit pointovos.utterance.speak(§9.6).
- The bus bridge: a participant that terminates an external channel and
relays Messages between the internal bus and remote participants. §3 —
the normative core: inbound identity stamping (
source), outbound routing bydestination/session_id/site_id,site_idassignment, and the relaying vs managing session-preservation modes. §4 — emergent patterns over MSG-1 + SESSION-1/2 + PIPELINE-1 + TRANSFORM-1 + CONTEXT-1 + INTENT-4 at a bus boundary: policy injection, multi-deployment topologies, out-of-utteranceovos.session.sync, and satellite skill registration. §5 ordering guidance; §6 conformance. - §3.3 —
site_idassignment is owned here; OVOS-SESSION-1 §3.3 carries the registry pointer and the orchestrator-pipeline consumer constraints.