symfonic.agent.cutover.container_semantics¶
container_semantics ¶
The agent container row's own semantics, rejected by name (TA8.41).
TA8.25 filed config.agent as subgroup C1-A, one row, and recommended
REJECT on the field's merits rather than for want of an owner: agent is
a typed grouping container, the only value the inventory ever drove through it
was agent.model, and every meaningful nested setting has a row and a
disposition of its own. Nothing independent is left for the container row to
mean.
What is rejected, and what is emphatically not. The agent object is not
withdrawn and is not refused wholesale -- doing that would refuse every adopter
who pins a model, which is most of them. What 11.0 rejects is the catch-all:
semantics attributed to the container that no child row owns. The owned
children continue under their own contracts, including
:data:~symfonic.agent.cutover.policy.ALLOWED_AGENT_FIELDS' model and
recursion_limit and C1-B's replacement for ask_user_pause_ttl_seconds.
Why this is a refusal and not a fallback. Today all three shapes below are
already rejected by :func:~symfonic.agent.cutover.envelope._nested_refusal
-- a substituted container class has no baseline to compare against, and an
unenumerable one has no fields to compare -- but rejected into the legacy body,
silently, because the envelope is default-deny. On a line that retires the
legacy body that silence stops being a fallback and starts being a drop. This
module says the same "no" out loud, before dispatch, on run, stream and
stream_typed alike.
Emptiness is not use, the same rule TA8.26 states for the twenty-five retired fields. A child whose owner is not recorded here refuses only when the adopter actually moved it off the stock value; left alone it asks for nothing and passes through untouched. The two structural shapes -- a substituted class, an unenumerable container -- are use by construction, because an adopter does not accidentally supply a different type.
UnownedContainerError ¶
Bases: RetiredConfigurationError
config.agent carried a semantic no child row owns.
Subclasses :class:~symfonic.agent.cutover.config_retirement.RetiredConfigurationError
so except RetiredConfigurationError around the agent API keeps catching
this -- the same widening-never-a-rename discipline that error states for
its own ancestry -- while an adopter who wants to tell the container
rejection from the twenty-five retired fields can catch the narrower class.
It is a subclass rather than a fourth sibling because it refuses the same
kind of thing at the same moment: a fact about how this agent was built,
named before dispatch. The vocabulary difference is the group, which is
:data:UNOWNED_CONTAINER_GROUP and is not a retired-settings group.
Source code in src/symfonic/agent/cutover/config_retirement.py
refuse_unowned_container ¶
Reject the container's own semantics on entry_point, or return.
The whole of C1-A's REJECT, expressed once and called from all three public
entry points -- the position, and the reasons for it, are
:func:~symfonic.agent.cutover.config_retirement.refuse_retired_setting's:
a verdict-driven rejection would be route-conditional, and a rolled-back
switch would re-honour what this line rejects.
Source code in src/symfonic/agent/cutover/container_semantics.py
unowned_container_semantics ¶
Why config.agent carries unowned semantics, or None.
Answers None -- "nothing attributed to the container itself" -- for the
ordinary case, which is every configuration whose agent is a stock-class
container carrying only owned children.
It also answers None when the question cannot be put: a config object
with no agent attribute at all, or one whose class cannot be
default-constructed to supply a stock container to compare against. That is
the one place this rule does not fail closed, and it is deliberate and
bounded: those objects are refused by
:func:~symfonic.agent.cutover.envelope._config_refusal on their own terms,
so answering "refuse" here would name the container for a defect that is not
the container's.