symfonic.agent.cutover.pause_admission¶
pause_admission ¶
Whether a pause-capable agent may be served by the kernel typed route (ST3).
HK1 (TA8.34) gave the kernel route a pause: a wired
:class:~symfonic.capabilities.human.capability.HumanInteractionCapability
folds a pre-tool stage and an ask_user tool into the compiled turn, and
:mod:~symfonic.agent.cutover.typed_interrupts renders the stopped run as an
AskUserQuestionEvent. HK2 (TA8.35) built the redemption for it. What neither
built is the half that connects the second to the public API, and this module
exists because ST3's flip is what would otherwise expose the gap.
The gap, stated exactly. A capability pause is minted as a signed envelope
and handed to the consumer as whatever string the composition root's
encode_token renders it as; the reverse mapping is that transport's, and the
engine is never given it. Both public redemption methods -- SymfonicAgent
.resume and .resume_interrupt -- decode only the HMAC PauseToken keyed
to the framework config, which is a different scheme. So a consumer paused on
the kernel typed route holds a token that no public method can redeem: not
one that fails a check, one that has no reader.
Why that decides admission rather than being documented. The condition ST3
was given is that flipping with a pause and no resume leaves a human-in-the-loop
consumer stopped on a route that cannot continue -- worse than not flipping. The
legacy body's pause is redeemable (resume re-enters the graph runtime with
a token it minted itself), so keeping such a deployment on
_stream_typed_impl is not a degradation; it is the only route where the
cycle closes. The turn is counted and attributed as a fallback exactly like any
other out-of-envelope turn, so the cutover's fallback rate stays readable.
The predicate is deliberately the same three facts
:func:~symfonic.capabilities.human.contribution.build_contribution reads.
A capability that contributes nothing cannot stop a run, so it cannot strand
one, and refusing it would keep deployments off the kernel route for a pause
they could never take.
TA8.45 narrowed this rather than deleting it. The engine now does reach
HK2's redemption: SymfonicAgent.resume and .resume_interrupt dispatch
invocation.continuation and, when the switch is on and the deployment wired
:attr:HumanInteractionCapability.decode_token, continue the paused turn on
the kernel. For such a deployment the cycle closes and the reason this module
exists is gone — the check returns None and the typed route is served by
the kernel.
Both halves of that sentence are asked, not one. The cycle closes only when
a reader exists and the continuation is actually routed to the kernel, so
:func:unredeemable_pause_reason takes continuation_served_by_kernel as a
required keyword rather than inferring it from decode_token. The two facts
are independent: invocation.continuation is a live rollback lever
(_rolled_back / process_rollback_reason, kept for T4.4.6/RET-11's
conformance suite and asserted as a live property by TA8.45's own revert test),
and a deployment that wired the reader and then reverted the continuation is
back in ST3's condition exactly — the kernel typed route would mint a
capability envelope and resume would hand that string to
:meth:SymfonicAgent._legacy_continuation_impl, which decodes only the HMAC
PauseToken and cannot read it. Reading only decode_token would admit
that turn and leave it out of the tally, which is the shape ST3 refuses:
stranded, and unmeasured.
What the check must not do is return None for a deployment that wired a
pause transport and no reader for it. That agent is exactly the one ST3
described: it can mint an envelope on the kernel typed route and no public
method can turn the consumer's string back into one. Deleting the check
outright would have stranded it, which is why the narrowing is to the missing
seam rather than to the task that added the seam. The two tests aimed at this
survive with it — they wire no decode_token, which is the state they were
written about.
unredeemable_pause_reason ¶
NO_PUBLIC_REDEMPTION if this capability could strand a turn, else None.
None for the overwhelming majority of agents, whose composition root
wired no pause transport at all and whose dispatch is unchanged by this
check — and, since TA8.45, None for a deployment that wired the reader
as well as the writer and still routes its continuation to the kernel,
because the public redemption door opens onto the kernel continuation for
exactly that deployment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
capability
|
Any
|
The agent's wired human-interaction capability, or |
required |
continuation_served_by_kernel
|
bool
|
Whether |
required |