Skip to content

spec/session-2: session lifecycle and state ownership#34

Closed
JarbasAl wants to merge 7 commits into
devfrom
spec/session2-lifecycle
Closed

spec/session-2: session lifecycle and state ownership#34
JarbasAl wants to merge 7 commits into
devfrom
spec/session2-lifecycle

Conversation

@JarbasAl

Copy link
Copy Markdown
Member

Summary

  • Adds session-lifecycle.md — OVOS-SESSION-2, the lifecycle complement to SESSION-1
  • Defines: state-ownership model, client-side merge rules, resumption semantics, default-session ownership rule, conformance roles
  • Central principle: stateless named sessions, orchestrator owns session_id == "default", mutation only at transformer/pipeline-match/handler boundaries

Status

Draft — needs review against:

  • SessionManager.sessions[] cache vs §2.2 stateless rule
  • expiration_seconds / TTL gap
  • is_speaking / is_recording out-of-band mutation exemption
  • active_skillsactive_handlers wire shape migration

Related

🤖 Generated with Claude Code

JarbasAl and others added 7 commits May 26, 2026 14:34
Companion lifecycle spec to OVOS-SESSION-1 (which defines only
wire shape and explicitly defers lifecycle). Closes the
"session lifecycle" gap APPENDIX §7 has tracked since the spec
set's inception, and is the normative reference CONTEXT-1 and
CONVERSE-1 have been forward-referencing.

What the spec defines:

- §2 State-ownership model:
  - 2.1 Bus is stateless transport
  - 2.2 Orchestrator is stateless for named sessions
  - 2.3 Orchestrator owns session_id == "default"
  - 2.4 The projection mandate — components MUST project
    cross-utterance session-keyed state into session-resident
    fields they own (via Match.updated_session per PIPELINE-1
    §4.2). Drives resumption parity (§5)
  - 2.5 Clients own their named sessions; persistence is their
    choice
  - 2.6 In-place session mutation only at transformer, pipeline,
    and handler boundaries — bus events do not mutate session
    in the current utterance

- §3 Per-utterance round: client emits → assistant runs
  PIPELINE-1 lifecycle → emits N responses, each carrying
  session at emission point → client receives and updates

- §4 Client-side merge rules — minimal and permissive:
  - session_id is the only key (no routing-data filtering;
    session_id uniquely identifies channels)
  - every assistant-emitted Message carries a valid session
  - ovos.utterance.handled is the canonical convergence point
    (no new topic needed)

- §5 Resumption is implicit. A client re-emits a previously-
  used session_id with held state at any time; orchestrator's
  statelessness for named sessions makes it work uniformly.
  Resumption-safe = session-resident. Per §2.4 projection
  mandate, nothing component-held is non-resumption-safe in a
  conformant deployment

- §6 Default-session ownership: orchestrator holds persistent
  in-process state for "default"; restart drops it (acceptable
  for local-device "fresh start" semantics); components keyed
  on default get effective persistence within deployment
  lifetime

- §7 Conformance for bus, orchestrator, component, client, and
  the special-case default-session client

- §8 Non-goals — no persistence protocol, no auth, no
  cross-client coordination, no lifecycle observability events

The §2.4 projection mandate has cascading effects on existing
in-flight specs (CONVERSE-1 in particular). Follow-up PRs will
land separately to revise CONVERSE-1's response-mode wait state
to project to session.response_mode as a structured field and
drop the side-band set/clear topics now made redundant.

Single file per AGENTS.md repo policy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-internal

Per design feedback: the strict MUST-project rule was too tight.
Real-world plugins (LLM transcripts, media playback state, learned
personalization, anything tied to external resources) cannot
practically project into session — the state is too large, too
coupled to external resources, or too sensitive.

Relax §2.4 to SHOULD-project-when-practical with an explicit
MAY-internal alternative. A component that takes the internal
path:

- owns its state lifecycle in full (persistence, expiry,
  eviction, multi-orchestrator coordination if applicable)
- offers best-effort resumption with no normative guarantee —
  a user asking "unpause the music" months later may or may not
  get a useful reaction, plugin's choice
- MUST NOT expect other components to know its state exists

Updates:
- §2.4 rewritten with concrete examples (LLM history, media
  playback state, personalization, external-resource ties) and
  explicit responsibility transfer
- §5.2 'projected state of every component bound by §2.4' →
  'projected state of every component that elected the
  SHOULD-project pathway'
- §5.3 rewritten: plugin-internal state is permitted with
  best-effort resumption; spec defines no protocol for it;
  resumption parity across plugins is not guaranteed
- §7.3 Component conformance split: MUST list keeps in-utterance
  cache discipline; SHOULD list governs projection; MAY allows
  internal state with the responsibility/resumption caveats
- §1 scope and 'builds on' list resoften language
- §3.1 cross-ref likewise

Both pathways are conformant; the choice is per plugin. The
CONVERSE-1 converse plugin still chooses projection (its state
is small and naturally session-coupled); the spec explicitly
calls this out as one example of the SHOULD path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- §2.3: align "default" framing with SESSION-1 §3.1 (interact with
  device-local session, not "originates from device")
- §3.2: clarify PIPELINE-1 is authoritative for lifecycle detail
- §5.2: SESSION-1 §2.5 → §2.1 (correct cross-ref for omission rule)
- §6.1: restate merge rule as omission-preserve first, present-replaces
  second; drop "last-write-wins" framing that clashed with SESSION-1 §2.1
- §6.4: drop ovos.session.sync / ovos.session.update_default topic names;
  deployer-defined topic only, no normative name
- §7.2: §4.4 → §4.3 (end-marker convergence point cross-ref)
- §8: collapse to one-paragraph; §1 is the canonical non-goals list

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Drop §3 per-utterance round entirely (was narrative glue restating
  PIPELINE-1 and §2; replaced with PIPELINE-1 §6 cross-ref at §2.2)
- §4.1 second paragraph removed ("also conformant to ignore the spec")
- §7.3 trivial MUST dropped ("treat caches as utterance-scoped")
- §2.5 second paragraph collapsed to one sentence (trust = layer-2)
- §5.2 field list replaced with "every field in SESSION-1 §3 registry"
- §6.3 cut by half; key point preserved
- §7.4 MAY list collapsed to one sentence pointing at §3 and §4
- §8 non-goals already collapsed; fix §5.2 cross-ref in it
- Renumber: old §5→§4, §6→§5, §7→§6, §8→§7; all internal refs updated

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…s-client disambiguation

- Intro: add TRANSFORM-1 as fifth companion spec; its six transformer
  hooks are the normative session-mutation boundaries cited in §2.6
- §1 non-goals: cross-client session sharing note now mentions that
  MSG-1 source/destination routing is the layer-2 disambiguation
  mechanism for which client owns a given session_id

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Specs must be timeless and standalone — no named implementation
projects. Replace two prose references to ovos-core and
SessionManager.default_session with implementation-agnostic
descriptions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…xamples, collapse non-goals into §1

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f89a6f94-26ba-4a2a-95a6-a78e1066d23c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch spec/session2-lifecycle

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@JarbasAl JarbasAl closed this May 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant