Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,29 @@ an entry here.
out of scope.
## OVOS-TRANSFORM-1 — Transformer Plugins

### 2

- §4 — chain order restated cleanly: ascending priority, `1` runs
first, default `50`; a priority assignment authored for the
inverse (descending) convention MUST be renumbered, since the two
orderings are exact inverses.
- §5.3 — the effective chain per injection point is composed once
per utterance lifecycle from the session as committed at
utterance start; mid-lifecycle mutations of the preference or
denylist fields take effect on the next utterance.
- §3.4 — the `Match` slot map is named `slots` (aligned with
OVOS-PIPELINE-1 §4.1); all `captures` wording renamed.
- Terminal-event topics — `ovos.intent.unmatched` replaces the
retired failure topic on the no-transcription and cancellation
paths (OVOS-PIPELINE-1 §9.3).
- OVOS-CONTEXT-1 pathway citations repointed (§5.1 engine-side,
§5.2 in-place transformer mutation, §5.3 `ovos.session.sync`);
the bus-event mutation topics dropped in favour of the sync
pathway; attribution precedence and cancellation-stamp rationale
stated locally.
- SESSION-1 registry claims corrected to §2.2; slot-typing
deferrals restated as timeless out-of-scope statements.

### 1

- Initial draft. Defines six transformer chains at six injection
Expand Down
98 changes: 56 additions & 42 deletions transformer.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Transformer Plugins Specification

**Spec ID:** OVOS-TRANSFORM-1 · **Version:** 1 · **Status:** Draft
**Spec ID:** OVOS-TRANSFORM-1 · **Version:** 2 · **Status:** Draft

This document defines **transformer plugins** as an architectural
pattern of voice operating systems: ordered black-box chains of
Expand Down Expand Up @@ -120,8 +120,8 @@ It does **not** define:
- **Slot value typing schemas.** Intent transformers (§3.4) are
the canonical home for system-type entity injection (dates,
numbers, durations, etc.), but the *typed value formats*
themselves are deferred to a future text-normalization
specification (OVOS-INTENT-1 §5.3).
themselves are out of scope for this specification
(OVOS-INTENT-1 §5.3).
- **Streaming / end-to-end pipeline shapes.** The §2 flow diagram
describes the canonical staged flow most transformers depend on
(mic → STT → text → intent → speak → TTS → playback);
Expand Down Expand Up @@ -184,9 +184,9 @@ each other and with the component-identity keys claimed by other
specifications — `context["skill_id"]` (OVOS-INTENT-4 §3.1) and
`context["pipeline_id"]` (OVOS-PIPELINE-1 §3.1), both **single
strings**. Attribution consumers that need to pick a single
emitter apply the precedence rule codified in OVOS-CONTEXT-1 §5.2
(most-specific by lifecycle position, reading the last element of
the list-valued keys).
emitter **SHOULD** take the identity most specific by lifecycle
position among the keys present, reading the last element of the
list-valued keys.

`<type>_transformer_ids` is the transformer chain's
**self-attribution**. It is distinct from any
Expand Down Expand Up @@ -403,7 +403,7 @@ applies here equally.
Two distinct outcomes share this shape: (1) **no plausible
transcription** — empty list without the §8.1 cancellation signal;
downstream stages treat it as silence and the lifecycle terminates
with `complete_intent_failure` followed by `ovos.utterance.handled`
with `ovos.intent.unmatched` followed by `ovos.utterance.handled`
per OVOS-PIPELINE-1 §9; (2) **cancellation** — empty list returned
together with `canceled: true` and `cancel_reason` per §8.1; the
orchestrator terminates via the §8.2 path, emitting
Expand Down Expand Up @@ -478,9 +478,9 @@ the universe of candidates deterministically.
> Mutating certain reserved keys has effects that spec readers
> should be aware of even though they are not prohibited:
>
> - Mutating `session.intent_context` directly bypasses OVOS-CONTEXT-1 §5
> bus-event stamping — no `origin` is stamped because the
> mutation does not ride the §5 bus events.
> - Mutating `session.intent_context` directly is the sanctioned
> transformer pathway of OVOS-CONTEXT-1 §5.2; the key-shape
> rules of OVOS-CONTEXT-1 §3 apply to every entry written.
> - Mutating `session.pipeline` (OVOS-PIPELINE-1 §5) changes which
> pipeline plugins are consulted for this utterance — a powerful
> per-utterance routing primitive that is also easy to misuse.
Expand All @@ -496,27 +496,27 @@ the universe of candidates deterministically.
the `Match` object that a pipeline plugin produced
(OVOS-PIPELINE-1 §4.1) before the orchestrator emits the dispatch
Message (OVOS-PIPELINE-1 §7). Two things happen in this window —
**engine-side session mutation** per OVOS-CONTEXT-1 §5.3 and the
**engine-side session mutation** per OVOS-CONTEXT-1 §5.1 and the
intent-transformer chain of this section — and the **engine-side
mutation MUST happen first**. The orchestrator accepts the match,
allows the matching engine to write any context entries it intends
to per CONTEXT-1 §5.3, and only then runs the intent-transformer
to per CONTEXT-1 §5.1, and only then runs the intent-transformer
chain over the resulting `Match`. This ordering lets an intent
transformer read context the matching engine just wrote (for
example, to enrich a capture based on a freshly-promoted entry).
example, to enrich a slot based on a freshly-promoted entry).

**Input.** The `Match` produced by the pipeline plugin that
claimed the utterance — `skill_id`, `intent_name`, `captures`,
claimed the utterance — `skill_id`, `intent_name`, `slots`,
`utterance` (OVOS-PIPELINE-1 §4.1) — together with the post-engine-
mutation `session.intent_context` snapshot.

**Output.** A `Match` of the same shape, possibly with an enriched
`captures` map.
`slots` map.

**Permitted mutations.** A transformer MAY add entries to
`Match.captures` and MAY overwrite existing entries it itself
`Match.slots` and MAY overwrite existing entries it itself
produced earlier in the chain. It **SHOULD NOT** delete or
overwrite capture entries produced by the matching engine or by an
overwrite slot entries produced by the matching engine or by an
earlier transformer in the chain, unless deletion is the
transformer's deployer-configured purpose (PII redaction,
content filtering, profanity censoring). It **MUST NOT** change
Expand Down Expand Up @@ -591,8 +591,7 @@ applied effects) for observability.
A chain runs in **ascending priority order**: a transformer with
`priority = 1` runs before one with `priority = 50` runs before one
with `priority = 100`. Lower number = earlier in the chain. This
matches the natural "stages count up" reading and the existing
fallback-skill ordering convention elsewhere in OVOS.
matches the natural "stages count up" reading.

Each transformer plugin declares an integer `priority`. The
default is `50` — the middle of the band — so plugins with no
Expand All @@ -615,12 +614,19 @@ Two ordering mechanisms are defined; deployers choose:
The orchestrator **MUST** support both mechanisms and **MUST**
apply explicit order when configured.

Priorities are meaningful only under ascending order. A priority
assignment authored for the inverse convention — descending order,
where the lowest number runs *last* and, because each transformer's
output overwrites its predecessor's, effectively "wins" — is the
exact inverse of a conformant one and **MUST** be renumbered; run
unrenumbered, such a chain executes backwards.

---

## 5. Per-session overrides

This specification claims **twelve session fields** under
OVOS-SESSION-1 §2.1: six **preference** fields naming a per-type
OVOS-SESSION-1 §2.2: six **preference** fields naming a per-type
chain ordering (§5.1) and six **policy** fields naming a per-type
denylist (§5.2). The composition rule of §5.3 layers them.

Expand All @@ -644,7 +650,7 @@ Six session fields, one per injection point, expressing the

Each field is OPTIONAL on the wire. An omitted, empty, or absent
field resolves at consumption to the deployment default for that
hook per OVOS-SESSION-1 §2.1. An empty array (`[]`) is wire-
hook per OVOS-SESSION-1 §2.2. An empty array (`[]`) is wire-
equivalent to omission for every field in the table above. Per
the canonical wire-weight rule of OVOS-SESSION-1 §3.4, a producer
**SHOULD** omit any of these fields whose value matches the
Expand Down Expand Up @@ -731,6 +737,17 @@ order, mirroring OVOS-PIPELINE-1 §5.5:
The result is the ordered list of transformers the orchestrator
invokes at that injection point for this utterance.

The effective chain for **each** injection point is composed
**once per utterance lifecycle**, from the session as committed at
utterance start. Mid-lifecycle mutations of the
`<type>_transformers` or `blacklisted_<type>_transformers` fields —
by a transformer, a match-phase `updated_session`, or a handler —
take effect on the **next** utterance, not the current one.
Composing each chain from a live session would let an earlier chain
rewrite which later chains run for the same utterance, making the
lifecycle's transformer surface depend on mutation timing rather
than on the state the utterance arrived with.

If every requested `transformer_id` is dropped by availability or
policy, the effective chain is empty for that injection point and
the orchestrator simply runs no transformers at that stage — the
Expand Down Expand Up @@ -1002,10 +1019,9 @@ observes a cancellation signal:

Stamped from the transformer that produced the signal (the
orchestrator knows which one), **not** from any value the
transformer included in the payload. This parallels OVOS-CONTEXT-1
§5.2's origin-stamping rule and serves the same purpose: a
transformer cannot impersonate another transformer's
cancellation.
transformer included in the payload. The orchestrator-side stamp
guarantees that a transformer cannot impersonate another
transformer's cancellation.

When `canceled: true` is observed alongside an empty utterance
list (§3.2) or any other artifact, the cancellation flag is the
Expand Down Expand Up @@ -1041,7 +1057,7 @@ signal that triggered the cancellation. `ovos.utterance.handled`
preserves the universal end-marker invariant of OVOS-PIPELINE-1
§9.5.

The orchestrator **MUST NOT** emit `complete_intent_failure`
The orchestrator **MUST NOT** emit `ovos.intent.unmatched`
(OVOS-PIPELINE-1 §9.3) on the cancellation path — failure and
cancellation are distinct outcomes; an observer that wants to
count "user gave up" or "policy blocked it" separately from
Expand Down Expand Up @@ -1090,7 +1106,7 @@ the orchestrator does not implement, no obligations arise.
- on any cancellation, emit `ovos.utterance.cancelled` followed
by `ovos.utterance.handled` (§8.2), carrying `cancel_reason` and
the stamped `cancel_by`, and **MUST NOT** emit
`complete_intent_failure` on the cancellation path; **MUST NOT**
`ovos.intent.unmatched` on the cancellation path; **MUST NOT**
strip the `canceled` / `cancel_reason` / `cancel_by` keys from
`Message.context` on the terminal events or downstream
derivations; **MUST NOT** dispatch a Match that was reached
Expand Down Expand Up @@ -1162,16 +1178,15 @@ covers.
- read and mutate `session.intent_context` (OVOS-CONTEXT-1 §2)
directly on the session object it holds in hand. The direct-
mutation pathway is normatively permitted for any transformer
type by OVOS-CONTEXT-1 §5.3 — the orchestrator is the carrier
type by OVOS-CONTEXT-1 §5.2 — the orchestrator is the carrier
of writes, not the bus. When mutating, the transformer **MUST**
use the key-shape rules of OVOS-CONTEXT-1 §3 and §5.3 (private
use the key-shape rules of OVOS-CONTEXT-1 §3 and §5.2 (private
entries prefixed `<skill_id>:`, where `<skill_id>` for a
transformer is its own `transformer_id` or, when the transformer
is writing on behalf of a specific skill, that skill's
`skill_id`). Mutations made via the bus (`ovos.context.set` /
`.unset` / `.clear`, OVOS-CONTEXT-1 §5) are also permitted; the
choice between direct and bus is the transformer's, with the
trade-offs catalogued in OVOS-CONTEXT-1 §5.3;
`skill_id`). Mutations made via the `ovos.session.sync` pathway
(OVOS-CONTEXT-1 §5.3) are also permitted; the choice between
the in-place pathway and the sync pathway is the transformer's;
- access the bus for side-effects unrelated to the transformer's
IO (logging, telemetry, cross-session signals) — but **SHOULD
NOT** make the transformer's output depend on bus responses
Expand All @@ -1197,10 +1212,9 @@ true` or `cancel_reason`:
- **Slot value typing schemas.** Intent transformers (§3.4) are
where typed system entities are injected, but the typed value
formats themselves (date encoding, number representation,
duration units) are deferred to a future text-normalization
specification (OVOS-INTENT-1 §5.3). This spec defines the
injection pathway; the future spec will define what gets
injected.
duration units) are out of scope for this specification
(OVOS-INTENT-1 §5.3). This spec defines the injection pathway
only, not what gets injected.
- **Behavioural contracts for any specific transformer type beyond
the IO shape and the canonical use-case list.** Whether an
utterance transformer normalizes contractions, translates,
Expand Down Expand Up @@ -1262,12 +1276,12 @@ true` or `cancel_reason`:
claims the six per-session transformer-override fields (§5), and
the deployment-default fallback rule for omitted fields.
- *Intent Context Specification* (OVOS-CONTEXT-1) — the
context-mutation pathways transformers may use. Both the bus
events (§5) and the direct-session-mutation pathway (§5.3) are
available; the choice is the transformer's per the conformance
rules of §9 of this spec.
context-mutation pathways transformers may use. Both the
`ovos.session.sync` pathway (§5.3) and the in-place
transformer pathway (§5.2) are available; the choice is the
transformer's per the conformance rules of §9 of this spec.
- *Intent Definition Specification* (OVOS-INTENT-3) — the intent
and `Match` model that §3.4 operates on; §7 capture-map shape.
and `Match` model that §3.4 operates on; §7 slot-map shape.
- *Sentence Template Grammar Specification* (OVOS-INTENT-1) — §5.3
deferred slot value typing, for which §3.4 of this spec is the
agreed injection home.