Skip to content

symfonic.agent.cutover.turn_effects

turn_effects

The memory effects a kernel turn reports on the legacy response (CORE-227).

projection used to write memory_entries_used=0 and extracted_ops=[] on every kernel turn, on the grounds that the kernel path could not fill them. It can: the retrieval stage counts what it admitted and the model adapter keeps the operations it stripped, and :mod:~symfonic.agent.backend.turn_observation carries both out of the call. This module opens that observation around the delegate's kernel call and turns it into the legacy fields.

run also gets the rest of legacy's final-text presentation. Legacy strips a directive the kernel's filter does not recognise -- a trailing bare {"ops": ...} object, a loose GRAPH_OPERATIONS tail, a fenced JSON tail -- and reports its operations, then strips citation tags. That is :func:~symfonic.agent.response_presentation.present_response, the engine-free copy whose drift the presentation parity tests catch. A turn whose tagged block the kernel already removed gets the citation strip only, because legacy strips one directive per reply. Streaming text is not rewritten: its deltas are already delivered, and its terminal must keep equalling them. Its done chunk still reports the operations of an untagged directive left in that text, because the folded extractor reads the same :func:present_response and files them; reporting only what the kernel stripped would say [] for operations the turn filed.

memory_entries_used

memory_entries_used(observation: TurnObservation | None) -> int

What retrieval admitted; zero when no retrieval stage reported.

Source code in src/symfonic/agent/cutover/turn_effects.py
def memory_entries_used(observation: TurnObservation | None) -> int:
    """What retrieval admitted; zero when no retrieval stage reported."""
    if observation is None or observation.recalled is None:
        return 0
    return observation.recalled

observing_turn async

observing_turn(scope: AbstractAsyncContextManager[Any]) -> AsyncIterator[TurnObservation]

Enter scope with one turn observation open, and yield it.

Source code in src/symfonic/agent/cutover/turn_effects.py
@asynccontextmanager
async def observing_turn(
    scope: AbstractAsyncContextManager[Any],
) -> AsyncIterator[TurnObservation]:
    """Enter ``scope`` with one turn observation open, and yield it."""
    with observing() as observation:
        async with scope:
            yield observation

presented_run_text

presented_run_text(text: str, observation: TurnObservation | None) -> tuple[str, list[dict[str, Any]]]

Legacy's visible final_response and extracted_ops for one run.

Source code in src/symfonic/agent/cutover/turn_effects.py
def presented_run_text(
    text: str, observation: TurnObservation | None
) -> tuple[str, list[dict[str, Any]]]:
    """Legacy's visible ``final_response`` and ``extracted_ops`` for one run."""
    if observation is None:
        return text, []
    if observation.extraction_seen:
        return strip_citation_tags(text), [dict(op) for op in observation.extraction_ops]
    presented = present_response(text)
    return presented.visible, [dict(op) for op in presented.ops]

stream_extracted_ops

stream_extracted_ops(text: str, observation: TurnObservation | None) -> list[dict[str, Any]]

The streamed reply's extracted_ops; the same set run reports.

The operations the kernel stripped, else those of the untagged directive left in text. text itself is not rewritten here.

Source code in src/symfonic/agent/cutover/turn_effects.py
def stream_extracted_ops(text: str, observation: TurnObservation | None) -> list[dict[str, Any]]:
    """The streamed reply's ``extracted_ops``; the same set ``run`` reports.

    The operations the kernel stripped, else those of the untagged directive
    left in ``text``. ``text`` itself is not rewritten here.
    """
    return presented_run_text(text, observation)[1]