"""In-memory capture sink for emitted CLI success envelopes.The deterministic-output substrate captures the verbatim emitted:class:`~core.json_contract.SchemaEnvelope` document so a recordedrun can be replayed and asserted byte-identical after masking (ADR``2026-06-30-deterministic-output-replay-substrate``). The sink is acontext variable holding a list; it is unset (``None``) in production,so :func:`record_emitted_envelope` is a no-op unless a:func:`capture_envelopes` scope has armed it — the emit path pays only asingle ``ContextVar.get`` when capture is off.This module deliberately has NO dependency on:mod:`core.json_contract`, so the emit path(:func:`core.json_contract.emit_json_success`) can feed it through acheap lazy import without an import cycle. Typed re-validation of acaptured document against the schema registry lives in:mod:`core.observability._golden`."""from__future__importannotationsfromcollections.abcimportIterator,MappingfromcontextlibimportcontextmanagerfromcontextvarsimportContextVar_CAPTURE_SINK:ContextVar[list[dict[str,object]]|None]=ContextVar("_aeat_envelope_capture_sink",default=None,)"""Active capture list for the current context, or ``None`` when capture is off."""
[docs]@contextmanagerdefcapture_envelopes()->Iterator[list[dict[str,object]]]:"""Arm envelope capture for the current context, yielding the sink list. Nesting-aware: when a sink is already active (e.g. armed by an outer replay scope), this reuses it rather than shadowing it, so a re-entered command's emitted envelope lands in the outermost armed sink. The reused case does not reset the outer sink on exit. Yields: The list that :func:`record_emitted_envelope` appends to; each entry is a shallow copy of an emitted envelope document. """existing=_CAPTURE_SINK.get()ifexistingisnotNone:yieldexistingreturnsink:list[dict[str,object]]=[]token=_CAPTURE_SINK.set(sink)try:yieldsinkfinally:_CAPTURE_SINK.reset(token)
[docs]defrecord_emitted_envelope(envelope:Mapping[str,object])->None:"""Append ``envelope`` to the active capture sink; a no-op when unarmed. Args: envelope: The already-redacted, emitted envelope document. """sink=_CAPTURE_SINK.get()ifsinkisnotNone:sink.append(dict(envelope))
[docs]defcapture_is_armed()->bool:"""Return whether an envelope-capture scope is active for the current context."""return_CAPTURE_SINK.get()isnotNone