Summary
Add a new grammar token to OVOS-INTENT-1 — <name> — that expands, inline,
to the contents of a named vocabulary (a .voc). It lets an author define a
reusable phrasing fragment once and reference it from many templates, instead
of re-inlining the same (a|b|c) group everywhere.
This is a net-new feature (padatious/padacioso do not have it), not a
formalization of existing behaviour. It is the "reusable template fragments"
gap recorded in APPENDIX.md §2.2 and §5.
Motivation
Every template in OVOS-INTENT-1 is self-contained. Common fragments — politeness
prefixes, articles, recurring phrasings — are duplicated across every template
and every .intent file in a skill. Home Assistant (hassil expansion_rules)
and Rhasspy (<rule> references) both solve this; OVOS has no equivalent.
Example today:
# greet.intent
(hello|hi|hey) [there] {name}
(good morning|good afternoon|good evening) [there] {name}
With the feature:
# greeting.voc
hello
hi
hey
good morning
good afternoon
good evening
# greet.intent
<greeting> [there] {name}
Design decisions (already made — do not relitigate)
-
Reuse .voc. Do NOT add a new .rule file role. A .voc is already a
named, slot-free set of localized phrasings. "Keyword vocabulary" and "inline
fragment" are consumed identically (expand to a phrase set); the only
difference is where the phrase set lands. That is not enough of a behavioural
difference to justify a new role/extension. A <name> reference resolves to
name.voc — and to .voc only, never .entity or .blacklist (those have
committed, specialised roles; .voc is the general-purpose phrasing set).
-
Token: <name>. Angle brackets — ASR output never contains < or >,
so they extend the §2 "metacharacters cannot be literal input" set cleanly.
name follows the same charset as a vocabulary/resource base name.
-
Eager, author-time resolution. The expander substitutes each
<name> with (branch1|branch2|...) — the referenced vocabulary's expanded
sample set joined as alternatives — before the existing [x]/()
expansion runs. After substitution the template is ordinary. The engine, the
wire contract, and the engine conformance rules are unchanged: the entire
blast radius is the expander.
-
Slot-free. A .voc has no named slots by definition, so a referenced
fragment is guaranteed slot-free. <name> references introduce no slots.
-
Recursive but acyclic. A .voc may itself contain <name> references;
resolution recurses. A reference cycle is malformed.
-
Scope: skill-local only. A shared/core vocabulary library is explicitly
out of scope for this issue. <name> resolves through the existing
resource precedence (OVOS-INTENT-2 §2.1), which does not preclude a core
library later, but no core library is to be designed or shipped here.
-
Terminology: "inline vocabulary reference", not "expansion rule". It is a
new way to reference an existing concept (a vocabulary), not a new construct.
Open decision (resolve in the PR)
An <name> reference to an undefined vocabulary: treat as malformed →
MUST reject (recommended, consistent with OVOS-INTENT-1 §3.6), or resolve to
empty? Recommendation: malformed. Confirm and document whichever is chosen.
Required spec changes
OVOS-INTENT-1 (sentence-template-grammar.md) — bump to Version 2
- §2 Input model — add
< and > to the structural metacharacter set that
cannot occur as literal input.
- §3 Grammar tokens — add a table row for
<name> (facet: expansion).
Add a new subsection (e.g. §3.7) defining the inline vocabulary reference: the
charset of name, that it resolves to a .voc (OVOS-INTENT-2), and that it
is resolved by the expander.
- §3.6 Malformed forms — add: a reference to an undefined vocabulary (per
the open decision); a cyclic reference chain; unbalanced </> joins the
existing unbalanced-metacharacter rule.
- §4 Expansion / §4.1 Reference enumeration — add a new first step:
resolve every <name> (recursively) by substituting the referenced
vocabulary's expanded sample set as an alternatives group, before the
existing [x]→(x|) step. Note the substitution may introduce new ()
groups, which the existing steps then handle.
- §7 Conformance — the Expander role MUST resolve
<name> references.
- Header version
1.1 → 2.
OVOS-INTENT-2 (locale-resource-formats.md)
- §1 / §4.3 — broaden the
.voc description from "localized keywords /
substrings" to "a named set of localized phrasings", consumed as a keyword
vocabulary and/or referenced inline via <name> (OVOS-INTENT-1).
- Note that a
.voc may itself contain <name> references (vocabularies
compose).
- Bump version + CHANGELOG entry if the PR author judges the change normative.
Repo
- CHANGELOG.md — new
### 2 entry under OVOS-INTENT-1.
- APPENDIX.md — update §2.2 and §5: the "reusable template fragments" gap is
now addressed for the skill-local case (shared/core library still open).
- README.md — spec table version for OVOS-INTENT-1.
Acceptance criteria
Process
- Per
README.md "Changing a specification": work on a branch, open a PR
(do not commit directly), bump the Version header, add a CHANGELOG entry.
- Branch from the latest
dev; open the PR against dev.
Summary
Add a new grammar token to OVOS-INTENT-1 —
<name>— that expands, inline,to the contents of a named vocabulary (a
.voc). It lets an author define areusable phrasing fragment once and reference it from many templates, instead
of re-inlining the same
(a|b|c)group everywhere.This is a net-new feature (padatious/padacioso do not have it), not a
formalization of existing behaviour. It is the "reusable template fragments"
gap recorded in
APPENDIX.md§2.2 and §5.Motivation
Every template in OVOS-INTENT-1 is self-contained. Common fragments — politeness
prefixes, articles, recurring phrasings — are duplicated across every template
and every
.intentfile in a skill. Home Assistant (hassilexpansion_rules)and Rhasspy (
<rule>references) both solve this; OVOS has no equivalent.Example today:
With the feature:
Design decisions (already made — do not relitigate)
Reuse
.voc. Do NOT add a new.rulefile role. A.vocis already anamed, slot-free set of localized phrasings. "Keyword vocabulary" and "inline
fragment" are consumed identically (expand to a phrase set); the only
difference is where the phrase set lands. That is not enough of a behavioural
difference to justify a new role/extension. A
<name>reference resolves toname.voc— and to.voconly, never.entityor.blacklist(those havecommitted, specialised roles;
.vocis the general-purpose phrasing set).Token:
<name>. Angle brackets — ASR output never contains<or>,so they extend the §2 "metacharacters cannot be literal input" set cleanly.
namefollows the same charset as a vocabulary/resource base name.Eager, author-time resolution. The expander substitutes each
<name>with(branch1|branch2|...)— the referenced vocabulary's expandedsample set joined as alternatives — before the existing
[x]/()expansion runs. After substitution the template is ordinary. The engine, the
wire contract, and the engine conformance rules are unchanged: the entire
blast radius is the expander.
Slot-free. A
.vochas no named slots by definition, so a referencedfragment is guaranteed slot-free.
<name>references introduce no slots.Recursive but acyclic. A
.vocmay itself contain<name>references;resolution recurses. A reference cycle is malformed.
Scope: skill-local only. A shared/core vocabulary library is explicitly
out of scope for this issue.
<name>resolves through the existingresource precedence (OVOS-INTENT-2 §2.1), which does not preclude a core
library later, but no core library is to be designed or shipped here.
Terminology: "inline vocabulary reference", not "expansion rule". It is a
new way to reference an existing concept (a vocabulary), not a new construct.
Open decision (resolve in the PR)
An
<name>reference to an undefined vocabulary: treat as malformed →MUST reject (recommended, consistent with OVOS-INTENT-1 §3.6), or resolve to
empty? Recommendation: malformed. Confirm and document whichever is chosen.
Required spec changes
OVOS-INTENT-1 (
sentence-template-grammar.md) — bump to Version 2<and>to the structural metacharacter set thatcannot occur as literal input.
<name>(facet: expansion).Add a new subsection (e.g. §3.7) defining the inline vocabulary reference: the
charset of
name, that it resolves to a.voc(OVOS-INTENT-2), and that itis resolved by the expander.
the open decision); a cyclic reference chain; unbalanced
</>joins theexisting unbalanced-metacharacter rule.
resolve every
<name>(recursively) by substituting the referencedvocabulary's expanded sample set as an alternatives group, before the
existing
[x]→(x|)step. Note the substitution may introduce new()groups, which the existing steps then handle.
<name>references.1.1→2.OVOS-INTENT-2 (
locale-resource-formats.md).vocdescription from "localized keywords /substrings" to "a named set of localized phrasings", consumed as a keyword
vocabulary and/or referenced inline via
<name>(OVOS-INTENT-1)..vocmay itself contain<name>references (vocabulariescompose).
Repo
### 2entry under OVOS-INTENT-1.now addressed for the skill-local case (shared/core library still open).
Acceptance criteria
<name>defined as a grammar token in OVOS-INTENT-1, resolving to a.voc.before
[x]/()expansion; worked example included.</>..vocdescription broadened in OVOS-INTENT-2; composition noted.OVOS-INTENT-3 beyond at most a one-line cross-reference.
Process
README.md"Changing a specification": work on a branch, open a PR(do not commit directly), bump the
Versionheader, add a CHANGELOG entry.dev; open the PR againstdev.