symfonic.capabilities.prompting.assembly¶
assembly ¶
The bridge from a compiled prompt to the kernel's own vocabulary.
The capability declares a stage and produces a value; it never calls the
kernel, and the kernel never imports this package. Both halves talk through
:mod:symfonic.kernel.contracts, which is the only import edge the dependency
matrix licenses from a capability — and the reason this module is four
functions rather than a runtime coupling.
The stage is registered into prompt-assembly with the compiled digest in
its frozen config. That is deliberate: the digest is what makes "this plan
compiled this prompt" checkable from the plan alone, without the plan carrying
the prompt text into every diagnostic dump.
compiled_instructions ¶
The compiled prompt as kernel instructions, or None when it is empty.
None rather than "" because the kernel's instructions field is
optional, and an empty string is a system prompt that says nothing —
indistinguishable downstream from a deployment that meant to send one and
lost it.
Source code in src/symfonic/capabilities/prompting/assembly.py
prompt_stage_descriptor ¶
prompt_stage_descriptor(compiled: CompiledPrompt, *, priority: int = -900, awaited_sources: int = 0, deferred_render_gate: bool = False) -> StageDescriptor
The stage this capability contributes, carrying the compile's identity.
No effects and no emitted events are declared: this is a compilation stage (STG-7), a pure function of plan, request and the resolved-input snapshot. A stage that claimed an effect it does not perform would widen its own admission for nothing, and under the reformulated STG-7 it would also be refused outright.
static_prompt_digest identifies this compile, not the final prompt.
The name is deliberate and the distinction is not pedantic. The digest
covers sources — what the capability was configured with, compiled here
at contribution time. It does not cover:
Agent(instructions=...), which the kernel's own stage puts on the assembly and this capability composes onto afterwards;- anything a resolution stage put in the turn's snapshot, which by definition does not exist yet when this descriptor is built;
- any contribution whose source must be awaited (S01).
contribute()is synchronous, so anaread-only source cannot be read here at all.awaited_sourcescounts them in the same config, because "the digest does not cover N of my sources" is a fact a plan reader needs and a silently narrower digest is exactly the false "checkable from the plan alone" claim the paragraph below retires. - the request's
render_whenpolicy, when one is set (S01).deferred_render_gaterecords that the digest compile ran without it. The gate is a turn-time decision over the whole set and may be awaited, so the synchronous declaration-time compile cannot honour it; running it here would refuse the plan outright for a policy the turn supports.
The field was called prompt_digest and read as "this plan compiled this
prompt, checkable from the plan alone". That claim was already false before
memory existed — the adopter's instructions were outside it — and the
reformulated STG-7 makes the gap structural rather than accidental. Naming
it for what it actually covers is the honest half; recording the final
digest is a runtime artifact and needs a carrier the kernel does not have
yet (see the debt table in the phase-4 sizing note).
Source code in src/symfonic/capabilities/prompting/assembly.py
to_prompt_assembly ¶
to_prompt_assembly(compiled: CompiledPrompt, *, prompt: str, attachments: tuple[Any, ...] = (), history: tuple[Any, ...] = ()) -> PromptAssembly
Project a compiled prompt into the kernel's prompt-assembly value.