diff --git a/CHANGELOG.md b/CHANGELOG.md index ad47b45..bccc0e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/session-2.md b/session-2.md index 341cffd..b48d0b0 100644 --- a/session-2.md +++ b/session-2.md @@ -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 @@ -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, @@ -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. @@ -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). @@ -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 @@ -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, @@ -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 @@ -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; @@ -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.