Skip to content

symfonic.capabilities.prompting.sources

sources

Source resolution and the failure policy that governs it.

The one thing this module never does is fabricate content. A source that cannot be read produces exactly one of three outcomes — the compile fails, the last known good revision renders (marked degraded), or the contribution is omitted (recorded) — and which one is a property of the contribution's tier unless the operator states otherwise.

last_known_good deliberately does not fall back to "render nothing" on its own authority. With no stored revision it defers to the tier default, so an authored block whose backend has never been reachable fails the compile rather than quietly shipping an agent without its rules on the first boot after a deployment.

InMemoryLastKnownGood dataclass

InMemoryLastKnownGood(_entries: dict[tuple[str, str], SourceRead] = dict())

A per-process store of the last revision each contribution served.

Keyed by :func:~.boundaries.isolation_key, so one tenant's stored profile can never be served into another tenant's prompt — the failure mode that makes a "just use the cached copy" fallback dangerous in a shared process.

SourceResolution dataclass

SourceResolution(read: SourceRead | None, diagnostics: tuple[PromptDiagnostic, ...] = (), degraded: bool = False)

The outcome of reading one contribution's source.

resolve_source

resolve_source(contribution: PromptContribution, *, scope_path: str = '', turn: int = 0, store: InMemoryLastKnownGood | None = None) -> SourceResolution

Read one contribution's source, applying its declared failure policy.

The synchronous door. A source that offers only aread is refused by name here rather than dropped: a silent drop is the defect this whole seam exists to avoid, and a compile that accepted the declaration and rendered none of it would be exactly the "accepted, validated, and never resolved" failure TA8.38 refused to ship.

Source code in src/symfonic/capabilities/prompting/sources.py
def resolve_source(
    contribution: PromptContribution,
    *,
    scope_path: str = "",
    turn: int = 0,
    store: InMemoryLastKnownGood | None = None,
) -> SourceResolution:
    """Read one contribution's source, applying its declared failure policy.

    The **synchronous** door. A source that offers only ``aread`` is refused by
    name here rather than dropped: a silent drop is the defect this whole seam
    exists to avoid, and a compile that accepted the declaration and rendered
    none of it would be exactly the "accepted, validated, and never resolved"
    failure TA8.38 refused to ship.
    """
    request = source_request(contribution, scope_path=scope_path, turn=turn)
    key = isolation_key(scope_path, contribution.contribution_id)
    if not is_sync_source(contribution.source):
        raise ContributionContractError(
            f"contribution {contribution.contribution_id!r} declares an asynchronous source "
            f"({type(contribution.source).__name__} offers aread() and no read()), and this "
            "compile went through the synchronous door. Await compile_prompt_async(request) "
            "instead; the synchronous compiler cannot read it and will not pretend it did."
        )
    try:
        read = contribution.source.read(request)
    except Exception as exc:  # noqa: BLE001 - every backend failure is one policy decision
        return _apply_policy(contribution, key, exc, store)
    if store is not None and contribution.failure_policy is SourceFailurePolicy.LAST_KNOWN_GOOD:
        store.put(key, read)
    return SourceResolution(read=read)

resolve_source_async async

resolve_source_async(contribution: PromptContribution, *, scope_path: str = '', turn: int = 0, store: InMemoryLastKnownGood | None = None) -> SourceResolution

Read one contribution's source, awaiting it when it asks to be awaited.

The asynchronous door, and the only new failure mode it introduces is cancellation, which is named ahead of the policy arm on purpose. CancelledError derives from BaseException rather than Exception, so the arm below would not have caught it anyway -- it is written out because a later edit widening that arm to BaseException would otherwise absorb a cancelled turn into on_source_failure and leave the turn running. PromptBlockResolver.resolve_block names the same hazard in the same words, and this seam is the one that brings that hazard onto the kernel line.

Source code in src/symfonic/capabilities/prompting/sources.py
async def resolve_source_async(
    contribution: PromptContribution,
    *,
    scope_path: str = "",
    turn: int = 0,
    store: InMemoryLastKnownGood | None = None,
) -> SourceResolution:
    """Read one contribution's source, awaiting it when it asks to be awaited.

    The **asynchronous** door, and the only new failure mode it introduces is
    cancellation, which is named ahead of the policy arm on purpose.
    ``CancelledError`` derives from ``BaseException`` rather than ``Exception``,
    so the arm below would not have caught it anyway -- it is written out
    because a later edit widening that arm to ``BaseException`` would otherwise
    absorb a cancelled turn into ``on_source_failure`` and leave the turn
    running. ``PromptBlockResolver.resolve_block`` names the same hazard in the
    same words, and this seam is the one that brings that hazard onto the kernel
    line.
    """
    request = source_request(contribution, scope_path=scope_path, turn=turn)
    key = isolation_key(scope_path, contribution.contribution_id)
    try:
        if is_async_source(contribution.source):
            read = await contribution.source.aread(request)
        else:
            read = contribution.source.read(request)
    except asyncio.CancelledError:
        # Cancellation is not a source failure. Swallowing it under ``omit``
        # would report a compiled prompt for a turn that is being torn down.
        raise
    except Exception as exc:  # noqa: BLE001 - every backend failure is one policy decision
        return _apply_policy(contribution, key, exc, store)
    if store is not None and contribution.failure_policy is SourceFailurePolicy.LAST_KNOWN_GOOD:
        store.put(key, read)
    return SourceResolution(read=read)

source_request

source_request(contribution: PromptContribution, *, scope_path: str = '', turn: int = 0) -> SourceRequest

The request one contribution's source is asked with, on one turn.

Source code in src/symfonic/capabilities/prompting/sources.py
def source_request(
    contribution: PromptContribution, *, scope_path: str = "", turn: int = 0
) -> SourceRequest:
    """The request one contribution's source is asked with, on one turn."""
    return SourceRequest(
        contribution_id=contribution.contribution_id,
        scope_path=scope_path,
        turn=turn,
        scope=contribution.scope,
    )