symfonic.agent.cutover.settings_contract¶
settings_contract ¶
What "a retired configuration field" means, and why each group is one (TA8.26).
The shape and the reasons. The twenty-five rows themselves live in
:mod:~symfonic.agent.cutover.retired_settings and the rule that reads them in
:mod:~symfonic.agent.cutover.config_retirement -- the same three-way split
:mod:~symfonic.agent.cutover.policy and
:mod:~symfonic.agent.cutover.envelope already make, and made for the same
reason: the trusted surface should be readable end to end without the
reflection that enforces it in the way, and each piece stays inside the
repository's module budget.
Why twenty-five fields at all. TA8.24's disposition plan grouped the 149
MISSING CONTRACT rows of the configuration admission inventory into clusters
and gave cluster C2 -- these twenty-five -- the recommendation RETIRE/REJECT,
on the finding that each names an implementation mechanic of the legacy body (a
phase-12 extractor, a nap loop, a promotion pass, a metacognition dial, a graph
state class, a dev checkpointer, a hydration route, a gate that no longer
exists) rather than a stable kernel capability. Today each merely falls to
legacy, because :func:~symfonic.agent.cutover.envelope.admit_invocation is
default-deny and no allowlist entry names it. Falling to legacy is the absence
of a decision: it says nothing to the adopter who set the field.
One rule, three declared inactivity classes. A field is used when its
value differs from the stock default and is not an inactive value. That is
one predicate, not twenty-five: :data:INACTIVE_CLASSES names the three ways a
value can ask for nothing and every row picks one. Emptiness is not use --
metacognition_sensitive_tags=[], nightly_nap_cron="" and
quick_nap_interval=0 are what a caller who wants nothing passes, and
refusing them would retire the parameter rather than the behaviour.
Groups, not a list. :data:RETIREMENT_GROUPS states the reason each group
refuses, once per group rather than once per field. The reason is the contract;
the twenty-five names are its coverage, and
tests/agent/cutover/test_retired_configuration.py asserts both halves --
because a parametrised sweep over the table proves the mechanism fires and
nothing at all about whether the right fields were chosen.
The stock defaults are mirrored, not imported. cutover deliberately
never imports :class:~symfonic.agent.config.FrameworkConfig; the envelope
reflects over whatever config object it is handed. So each row states the
default it was written against, and the test file fails if any of the
twenty-five drifts from the value the model actually declares -- the same
discipline LEVER_RETIREMENT_LINE keeps with the normative release constant.
RetiredSetting
dataclass
¶
One retired configuration field: its group, its default, its next step.
instead lives here rather than being supplied at the raise site for the
reason :class:~symfonic.agent.cutover.retirement.RetiredArgument gives: a
refusal that names the line and stops is a dead end, and a table that
carries the next step makes that obligation structural instead of
conventional. Where nothing replaced the field, instead says so in
those words rather than trailing off.
is_use ¶
Did the caller actually ask for this field's behaviour?
Fails closed. A value whose comparison to the stock default cannot be
answered -- an __eq__ that raises, a lazily imported stub, an
adopter object with an opinionated __len__ -- counts as use, for
the reason :func:~symfonic.agent.cutover.baseline.equivalent gives
for answering False: on an admission decision "I do not know" is
"no", and on a retirement it is "refuse".