Skip to content
Draft
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
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,25 @@ version 2: its `{{ … }}` sequences become substitution points, and its

## OVOS-SESSION-2 — Session Lifecycle and State Ownership

### 2

- §5.1 — the two write paths onto the default session
disambiguated: a committed `Match.updated_session` (PIPELINE-1
§4.2) is a complete snapshot and replaces the working session
wholesale (deletion by omission); inbound client Messages merge
field-by-field and cannot delete a stored field by omission.
- §3.2 — thin intermediate emissions: the full session object is
REQUIRED on dispatch Messages and on the terminal lifecycle
events clients adopt from; intermediate/status emissions MAY
carry only `{"session_id": ...}`.
- §2.5 — the flip side of client authority stated: a boundary
component injecting policy fields MUST re-apply them on every
inbound Message (OVOS-BRIDGE-1 §4.1 gate invariant).
- Citations — SESSION-1 registry claims corrected to §2.2 (§2.4,
§7); restart-loss citation corrected to §5.2; companion-spec
count corrected to six; CONTEXT-1/CONVERSE-1 field attribution
in the intro untangled.

### 1

- The state-ownership model (stateless bus, stateless orchestrator for
Expand Down
45 changes: 37 additions & 8 deletions session-2.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Session Lifecycle and State Ownership Specification

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

This document defines **who owns session state**, **when it is
mutated**, **how it propagates between client and assistant**, and
Expand All @@ -26,7 +26,7 @@ time, lets an orchestrator restart without losing client-side
continuity, and lets multiple orchestrators in a deployment serve
the same session without coordination.

It builds on five companion specifications:
It builds on six companion specifications:

- the *Bus Message Specification* (OVOS-MSG-1) — the envelope,
routing keys, `forward` / `reply` / `response` derivations,
Expand All @@ -48,8 +48,9 @@ It builds on five companion specifications:
*Active Handlers and Interactive Response Specification*
(OVOS-CONVERSE-1) — both elect the §2.4 SHOULD-project
pathway for their cross-utterance state (intent-context
entries, active-handler list, response-mode wait window
respectively), making it resumption-safe by construction.
entries for CONTEXT-1; the converse-handler list and
response-mode wait window for CONVERSE-1), making it
resumption-safe by construction.

The key words **MUST**, **MUST NOT**, **SHOULD**, **SHOULD NOT**,
**MAY**, and **RECOMMENDED** are used as in RFC 2119.
Expand Down Expand Up @@ -168,7 +169,7 @@ Behaviour rules for the default-session store are in §5.
A component (a pipeline plugin, a transformer, any other
participant) that holds `session_id`-keyed state **across**
utterances **SHOULD** project that state into a session-resident
field it owns (claimed under SESSION-1 §2.1) when projection is
field it owns (claimed under SESSION-1 §2.2) when projection is
practical. Projection flows through the pipeline plugin's
`Match.updated_session` channel (PIPELINE-1 §4.2) or through
in-place mutation at transformer / handler boundaries (§2.6).
Expand Down Expand Up @@ -238,7 +239,12 @@ the user's cloud, anything else.

Trust and authorization are layer-2 concerns (§1); this spec
places no constraint on what `session_id` or `session` value a
client sends.
client sends. Client authority has a flip side for boundary
components: one that governs a client by injecting policy fields
into its session **MUST** re-apply them on every inbound Message,
not once at connect — the client may legitimately omit those
fields on any later Message (OVOS-BRIDGE-1 §4.1, the gate
invariant).

### 2.6 When session mutates in place

Expand Down Expand Up @@ -393,6 +399,19 @@ policy. More elaborate policies (field-by-field merge, selecting
by emitter identity) are also conformant; the spec does not
prescribe.

**Thin intermediate emissions.** The full session object is
REQUIRED on dispatch Messages (PIPELINE-1 §7) and on the terminal
lifecycle events a client may adopt from (`ovos.utterance.speak`,
`ovos.utterance.handled`). Intermediate and status emissions — the
handler-lifecycle trio, progress notifications, and other
no-payload broadcast events — MAY instead carry a thin session of
only `{"session_id": ...}`. A fully populated session rides every
derivation (SESSION-1 §3.4); repeating it on every status event
multiplies traffic across bridges and layer-2 links for Messages no
conformant client needs to merge from. A client that adopts from an
intermediate emission gets at worst a thinner snapshot; the §3.3
convergence point always carries the full object.

### 3.3 `ovos.utterance.handled` is the canonical convergence point

When a client wants a single canonical "round is over" snapshot,
Expand Down Expand Up @@ -496,6 +515,16 @@ field. This is the natural complement to the stateless-named-
session rule: the default-session store fills the role the
client plays for named sessions.

The field-by-field merge rule above applies to **inbound client
Messages** only. A committed `Match.updated_session`
(PIPELINE-1 §4.2) is a complete snapshot: the orchestrator
**MUST** replace the working session snapshot with it
wholesale — a field absent from `Match.updated_session` is
deleted, not preserved. Deletion by omission exists only on
this pathway; an inbound client Message cannot delete a stored
default-session field by omitting it, only overwrite it by
sending a new value.

### 5.2 Restart semantics

The default-session store is **process-local**. An orchestrator
Expand Down Expand Up @@ -581,7 +610,7 @@ A component that holds `session_id`-keyed state across
utterances **SHOULD**:

- project that state into a session-resident field it claims
under SESSION-1 §2.1 (per §2.4), via the appropriate
under SESSION-1 §2.2 (per §2.4), via the appropriate
in-utterance pathway — `Match.updated_session` for pipeline
plugins per PIPELINE-1 §4.2, direct mutation for
transformers and handlers per §2.6;
Expand Down Expand Up @@ -654,6 +683,6 @@ The per-utterance session propagation (§2.6) and end-marker

See §1 for the full list of non-goals. This section adds one
clarification: **default-session persistence across orchestrator
restart** is not defined here. §5.3 makes restart-loss
restart** is not defined here. §5.2 makes restart-loss
explicit and intentional; persistence is deployer policy if
desired.