Skip to content

symfonic.core.prompt.blocks.sources.static

static

StaticBlockSource -- a prompt block pinned as a config literal.

BOUNDARIES is the block this exists for. A safety rule that lives as a literal in the framework config is immutable at runtime, reviewable in the diff that introduced it, and readable when every datastore on the network is down. This adapter serves exactly that -- one instance backs one string -- and nothing else. It performs no I/O of any kind, on any path.

The revision is constant, and that is the point

:attr:~symfonic.core.prompt.blocks.types.BlockRevision.revision is sha256:<hex> over the literal, computed once at construction and returned unchanged by every subsequent :meth:StaticBlockSource.load. Two properties follow, and both are load-bearing:

  • It never invalidates the prompt cache. The revision is a pure function of the configured text, so it is identical on every call, in every process, on every host that deployed the same config. A revision that moved -- a counter, a timestamp, an id(self) -- would re-bill the whole cached prefix on a block whose content is by definition incapable of changing while the process runs.
  • It still changes when the operator edits the literal. The next deployment hashes different bytes and gets a different revision, so a cache keyed on it cannot go on serving the retired boundary text.

There is deliberately no way to override the revision with a label of the operator's choosing. Such a label is a second source of truth for "has this changed", and the failure it enables is silent and severe: an operator edits BOUNDARIES, forgets to bump revision="v3", and every cache on the fleet keeps serving the old safety rules under a revision that claims to be current. The content hash cannot be forgotten.

What this source deliberately cannot do

  • No history. A literal has exactly one state -- the one in the config that is loaded. The adapter does not present list_revisions / load_revision, so isinstance(src, HistoryCapableBlockSource) is False and :func:~symfonic.core.prompt.blocks.validation.check_operator_editable rejects operator_editable=True against it at construction. Version control holds the history of that config file; this adapter does not read version control, and claiming a capability it has not implemented is what the structural Protocols exist to prevent.
  • Not scope-aware. One literal is one value for the whole deployment, so scope_aware is False and scope is accepted and ignored. Pairing it with a non-deployment block scope is a construction-time error in :func:~symfonic.core.prompt.blocks.validation.check_scope_pairing; it is never quietly served as per-tenant content.
  • Single block. block_id is accepted (the Protocol has no overload that omits it) and ignored, because the configured literal -- not the id -- is the content.

:meth:load raises nothing. There is no backing system to be unreachable, so there is no failure for the block's on_source_failure policy to route: the only way this adapter can be wrong is to have been configured wrong, and that is rejected at construction instead.

StaticBlockSource

StaticBlockSource(content: str)

Serves one prompt block from one string fixed in config.

Satisfies :class:~symfonic.core.prompt.blocks.protocol.BlockSource structurally and stops there -- see the module docstring for why history is not presented.

Parameters:

Name Type Description Default
content str

The block body. Hashed once here to produce the constant revision. Rejected when blank: an empty literal renders an empty labelled section, which reads to the model as a boundary section that exists and says nothing, and is in practice a half-finished config rather than an intent.

required

Attributes:

Name Type Description
offline_safe bool

Always True. The content is already in memory before the first turn; no read of it can fail.

scope_aware bool

Always False. One literal serves the whole deployment.

Source code in src/symfonic/core/prompt/blocks/sources/static.py
def __init__(self, content: str) -> None:
    if not isinstance(content, str):
        raise TypeError(
            "StaticBlockSource requires the block content as a str; got "
            f"{type(content).__name__}. The value is rendered into the prompt "
            "verbatim, so coercing it here would hide a config mistake behind "
            "a repr()"
        )
    if not content.strip():
        raise ValueError(
            "StaticBlockSource requires non-blank content; a blank literal "
            "renders a labelled block with an empty body, which is a "
            "half-written config rather than a deliberate empty boundary. "
            "Remove the block from the config to omit it"
        )
    self._content = content
    # Computed once, then never recomputed: the revision must be
    # byte-identical on every call so the cached prefix keyed on it
    # is never invalidated by a block that cannot change.
    self._revision = content_revision(content)

content property

content: str

The literal this source serves. Fixed at construction.

revision property

revision: str

The constant revision id -- sha256:<hex> of :attr:content.

current_revision async

current_revision(scope: TenantScope, block_id: str) -> str

Return the constant revision without building a revision object.

Not part of :class:BlockSource; offered for parity with :class:~symfonic.core.prompt.blocks.sources.file.FileBlockSource so a cache-validity check has one shape across adapters. Here it is a field read, so the check costs nothing.

Source code in src/symfonic/core/prompt/blocks/sources/static.py
async def current_revision(self, scope: TenantScope, block_id: str) -> str:
    """Return the constant revision without building a revision object.

    Not part of :class:`BlockSource`; offered for parity with
    :class:`~symfonic.core.prompt.blocks.sources.file.FileBlockSource`
    so a cache-validity check has one shape across adapters. Here it
    is a field read, so the check costs nothing.
    """
    return self._revision

load async

load(scope: TenantScope, block_id: str) -> BlockRevision

Return the configured literal and its constant revision.

scope and block_id are accepted because the Protocol has no overload that omits them, and ignored because one instance backs one literal.

Never raises: there is no backing system to be unreachable.

Source code in src/symfonic/core/prompt/blocks/sources/static.py
async def load(self, scope: TenantScope, block_id: str) -> BlockRevision:
    """Return the configured literal and its constant revision.

    ``scope`` and ``block_id`` are accepted because the Protocol has
    no overload that omits them, and ignored because one instance
    backs one literal.

    Never raises: there is no backing system to be unreachable.
    """
    return BlockRevision(
        content=self._content,
        revision=self._revision,
        # created_at / author / message stay unset. A config literal
        # records no author and no edit time -- version control does,
        # and this adapter does not read it. Filling them here would
        # make framework filler indistinguishable from provenance the
        # source actually knew.
        content_hash=self._revision.split(":", 1)[1],
    )