← APPENDIX.md · Non-normative
- Session preference fields not claimed by a spec.
SESSION-1 defines the wire shape and OVOS-SESSION-2 defines
the lifecycle and state-ownership model;
persona_idis claimed by OVOS-PERSONA-1. What remains deferred is the rest of the session preferences OVOS carries (time_format,date_format,system_unit,tts_preferences,location, …) — these need to be claimed under SESSION-1 §2.2's field registry by their respective owning specs (a preferences spec, OCP / locale specs as appropriate). - Text normalization of ASR output. The basis on which a typed slot's value is computed (INTENT-1 §5.6). Deferred to its own specification.
- A machine-checkable conformance corpus of
template → sample setpairs for INTENT-1 expansion, so expander conformance can be verified automatically. A parallel corpus of bus-message fixtures for MSG-1 would be the equivalent at the bus layer. - An end-to-end worked example. The specs have local examples; none shows a single skill defining one keyword intent and one template intent through the whole path — files, registration, match, handler.
- Conversation-level evaluation infrastructure. Rasa has story-based testing and end-to-end success metrics; the OVOS specs have no counterpart.
- OVOS-INTENT-2 ↔ hassil
intentstranslation tool. The grammar lineage (§2.1) makes a mechanical translator between OVOS-INTENT-2 locale resources and HA'sintentsYAML feasible. Such a tool would let the two corpora cross-pollinate without either format changing. Sits at injection point 3 of §3.3 conceptually but is build-time rather than runtime tooling. - GUI interactive companions. GUI-1 §3.4 reserves the
names
SYSTEM_confirm(a yes/no companion to a spoken question) andSYSTEM_select(a choice companion to a spoken set of options) without defining them. Both need a return channel from the display back to the assistant, and no such channel is specified — defining the templates without it would leave every backend inventing its own. The names are held so that no application-defined template claims them; a future version defines the pair together with the return path. - An identifier in a dotted topic, at one surface.
MSG-1 §2.1.1 confines identifiers to the
<skill_id>:<intent_name>dispatch shape and makes every dotted topic a static string. PIPELINE-1 §10's per-plugin introspection surface,ovos.pipeline.<pipeline_id>.intents.list, still builds a topic from a runtime identifier, which is the one place the family's topic surface is not enumerable from the specs alone. Whether the surface moves to a static topic withpipeline_idin the payload — the shape the poll families took — is unresolved. - i18n corpus. OVOS-INTENT-2 defines the locale file
format, and
ovos-localize(§1.4) provides the operations layer; what remains is the scale of the translated corpus. - Scheduled events were unspecified. No spec previously
claimed the timed and recurring event surface a voice OS
needs for alarms, timers, and reminders. OVOS-SCHEDULER-1 now
claims it; the legacy
mycroft.scheduler.*protocol is mapped to it, with divergences and an adoption roadmap, in appendix/scheduler.md.
- Multi-hop bridge cascading. BRIDGE-1 §4.2 describes peer-to-peer topology between two deployments, but does not address cascaded bridges (deployment A ↔ bridge ↔ deployment B ↔ bridge ↔ deployment C). Each bridge stamps source independently; outer-deployment participant identity is lost at each inner boundary unless propagated as opaque metadata.
- Bridge-to-bridge wire format. The spec does not prescribe whether messages between peer bridges remain in MSG-1 envelope form or may use a different serialization. The intent is that they stay in MSG-1 form (per §4.2 "relays native bus messages"), but the transport encoding is left as a deployment concern.
- Bridge health / heartbeat. No
ovos.bridge.ping/ovos.bridge.pongsurface is defined. The orchestrator has no spec-level way to know whether a remote participant is reachable. Deferred to a separate observability specification if needed. - Outbound audio over the bus is specified; inbound is not.
BRIDGE-1 §4.2.1 describes two audio-stack placements — local
(satellite runs STT and its own audio-output layer) and
hub-side (hub runs the full audio stack). On the output side
the bus surface is defined by OVOS-AUDIO-1:
ovos.utterance.speak.b64→ovos.audio.speechfor remote-client TTS delivery, and base64audiopayloads onovos.audio.queue/ovos.audio.play_soundfor sound effects. OVOS-AUDIO-IN-1 §1 explicitly scopes audio capture out ("acquisition mechanism is deployer-defined"), so what remains undefined is the inbound leg of the hub-side model — transmitting raw captured audio from the satellite to a hub-side STT as bus Message payloads (topic names, payload shape, session fields for codec and audio preferences). - Session-scoped pipeline plugin registration. BRIDGE-1 §4.3 and INTENT-4 §11 cover session-scoped intent registration for satellite-side skills. A satellite that implements a pipeline plugin (not an intent-based skill) cannot register that plugin on the hub; no bus surface exists for session-scoped plugin loading. If needed, this requires a new specification or an extension to OVOS-PIPELINE-1.
- Managing mode concurrent utterance race. BRIDGE-1 §3.4.2
says the bridge SHOULD apply
ovos.utterance.handledsession updates before injecting the next utterance, and already defines a MAY-fallback for the race — inject using the last known session state, with the orchestrator supplying the updated session on the followingovos.utterance.handled. What is left open is the policy for a second utterance arriving before the first round resolves: whether the bridge queues it, drops it, or forwards it against the stale session. A revision may define a normative queuing policy. - NAT bijection and hub-side session cleanup. When a bridge
using
session_idNAT (§3.2) disconnects a participant, the hub-sidesession_idmay remain in the orchestrator's default-session store (SESSION-2 §5). BRIDGE-1 §3.2 says the bridge SHOULD emit cleanup events using the hub-sidesession_idbefore dropping the bijection, but does not define a complete cleanup protocol for hub-side state created during the session's lifetime (e.g. cross-utterance context, active handlers). Deferred to a separate session-lifecycle specification. - Configuration change topics. No specification names
configuration.patch,configuration.updatedorconfiguration.patch.clear, but plugins emit them and ovos-config receives them. The payload question is ruled: decisionconfiguration-patch-clause-2, closed 2026-09-13, chose complete top-level values, no required order againstconfiguration.updated, and no full-configuration payload. The clause below states that ruling, and waits only for a specification to carry it:configuration.patchdata.configMUST be an object that carries, for each top-level key it changes, the complete runtime value of that key. An emitter MUST NOT send the full merged or full file configuration, and SHOULD send only the top-level keys it changes.- A receiver replaces the whole value of each top-level
key of
data.configin a runtime layer that overrides every configuration file. It does not merge into the value already there. The layer stays untilconfiguration.patch.clear. configuration.updatedhas no required payload. A receiver reloads its configuration files and MUST NOT clear the runtime layer.- No order between the two topics is required. A receiver
MUST NOT depend on one.
Reason for rule 1: receivers keep the payload above every
file, so a full-configuration payload makes later file edits
have no effect until
configuration.patch.clear. Reason for the "complete value" in rule 1, which rule 2 forces: a receiver replaces the key whole, so a partial value under a key discards any earlier patch of the same key. A plugin that patchestts.module, followed by one that patches{"tts": {"fallback_module": ...}}, loses the first value back to the file, with nothing logged. This pair states the behaviour that ships today (ovos-configConfiguration.patchassigns__patch[k] = v). A deep merge in the receiver, which would keep both patches, was the alternative put toconfiguration-patch-clause-2and was not chosen: it would change ovos-config rather than describe it. The SHOULD in rule 1 is deliberate. No ovos-config emitter computes a difference, so an emitter conforms only when its caller passes one. A MUST there would make the shipped emitters non-conforming on a caller's behaviour they do not control. The MUST NOT on the full configuration is what the reason above needs, and the emitters do satisfy that.