symfonic.agent.cutover.prompt_block_contract¶
prompt_block_contract ¶
C1-F and C1-O: what a prompt block becomes on the kernel line (TA8.38).
Fourteen rows -- prompt_blocks and the thirteen members of
:class:~symfonic.core.prompt.blocks.spec.PromptBlockSpec that TA8.25 counted
separately -- and this module is the written argument for why TA8.38 did not
apply their recorded NORMALISED_PER_ROW disposition as "route the retained
specs through the kernel prompting contribution".
TA8.51 supersedes half of this argument, and the half it supersedes is
named here rather than left for a reader to notice. TA8.38's override rested
on two facts: the port could not carry these rows, and admitting the field
without a port would accept specs and resolve none of them. S01 (TA8.51) built
the port -- AsyncContributionSource.aread beside the unchanged
ContributionSource.read, awaited by
:func:~symfonic.capabilities.prompting.compiler.compile_prompt_async, driven
per row on the kernel's run, stream and stream_typed doors -- so the
first fact is no longer true and this module no longer claims it.
The second fact stands, and it is now the whole reason these rows are still
MISSING CONTRACT: a port is not an admission. Nothing yet routes
config.prompt_blocks into a PromptContribution, no per-row parity has
been measured between a PromptBlockSpec and the contribution it maps onto,
and ALLOWED_FRAMEWORK_FIELDS is unchanged. Admitting the field on the
strength of "the seam exists" would assert that the migrated path honours the
value, which is the session_id mistake with a newer excuse. The follow-up
that owes that work is named in :func:async_seam_argument.
Historical note, kept because the mapping below was written against it. The
original mismatch was real: ContributionSource.read(SourceRequest) was an
ordinary synchronous call while
:class:~symfonic.core.prompt.blocks.protocol.BlockSource declared
async def load(scope, block_id) and PromptBlockResolver awaited it.
TA8.38 refused to route the rows across that gap rather than pretending it was
not there.
The rule neither lane will break is the one TA8.19 found broken for
session_id: a value threaded to nothing is not migrated. Putting
prompt_blocks on
:data:~symfonic.agent.cutover.policy.ALLOWED_FRAMEWORK_FIELDS today would
assert that the migrated path honours it at any value, and no route reads it at
any value -- :meth:SymfonicAgent._build_block_injector is reached from the
legacy prompt paths only, and the kernel route compiles from the bundle's
single HmsSystemSource. The specs would be accepted, validated, and never
resolved.
The capability was written down before it was wired, which is what let
TA8.51 start from a mapping rather than from thirteen field descriptions.
:data:PROMPT_BLOCK_CONTRACT names, per row, the member of the kernel
contract that carries the same meaning. That is the "write the new contract
before the code depends on it" half of a REPLACE, published ahead of a
migration TA8.38 could not finish. Four rows had no counterpart when it was
published and said so in those words rather than being quietly dropped -- the
honest output of a mapping exercise is the holes it found. TA8.51 built the
four members those holes named, so every row now maps onto a member that
exists, and :data:SEAM_BUILT_PROMPT_BLOCK_ROWS keeps the record of which four
had to be built rather than found. That set is the cost of the move, recorded
rather than absorbed.
What TA8.38 did move. Before it, all fourteen rows recorded unknown on
run and stream and had no stream_typed measurement. They are driven
on all three and record refused-to-legacy by name -- a decision rather than
an absence. That refusal is the envelope's default-deny, not a refusal contract
in TA8.26's sense; calling it one would be the "silence, not a refusal" mistake.
async_seam_argument ¶
The override argument, in one place, for every row that cites it.
A function rather than fourteen copies of a paragraph: the argument is one argument, and fourteen spellings of it would be fourteen chances for the reason to drift from the evidence.
Rewritten by TA8.51, because its first half stopped being true. TA8.38 wrote this when the port could not carry these rows at all; S01 built the port, so the sentence "the contract does not have an asynchronous source seam" would now be a false statement standing as fourteen rows' recorded reason. What survives unchanged is the half that actually keeps the rows refused: a port is not an admission, and nothing yet routes the configuration value through it.