"""Public extraction entry point. ``extract_session`` is the only function workers call. It builds a :class:`SessionContext` once and fans the registered feature functions across it. Pure library: no I/O, no bus, no DB. The worker (``BEHAVE-INTEGRATION.md`` Phase 4) is responsible for those. """ from __future__ import annotations from typing import Iterable, Iterator from behave_core.spec.envelope import Observation from decnet.profiler.behave_shell._ctx import SessionContext, build_session_context from decnet.profiler.behave_shell._features import FEATURES from decnet.profiler.behave_shell._parse import AsciinemaEvent DEFAULT_SOURCE = "decnet/profiler/behave_shell/extract.py" def extract_session( events: Iterable[AsciinemaEvent], *, sid: str, source: str = DEFAULT_SOURCE, evidence_ref: str | None = None, ) -> Iterator[Observation]: """Yield BEHAVE-SHELL observations for a single session. ``events`` is an iterable of ``(t, kind, data)`` tuples — see ``_parse.AsciinemaEvent``. ``sid`` identifies the session for evidence pointers and downstream joins. """ ctx = build_session_context( events, sid=sid, source=source, evidence_ref=evidence_ref ) for feature_fn in FEATURES: yield from feature_fn(ctx) def build_context( events: Iterable[AsciinemaEvent], *, sid: str, source: str = DEFAULT_SOURCE, evidence_ref: str | None = None, ) -> SessionContext: """Expose the SessionContext build for tests + future debug tools.""" return build_session_context( events, sid=sid, source=source, evidence_ref=evidence_ref )