symfonic.agent.cutover.governance_contract¶
governance_contract ¶
What "a C1-K governance surface" is, and the two names its rows refuse by.
The shape and the vocabulary. The three rows themselves live in
:mod:~symfonic.agent.cutover.governance_surfaces and the contract that
explains why each is a REPLACE lives in
:mod:~symfonic.agent.cutover.authority -- the same contract / data / rule
split :mod:~symfonic.agent.cutover.settings_contract,
:mod:~symfonic.agent.cutover.retired_settings and
:mod:~symfonic.agent.cutover.config_retirement already make, and made for the
same two reasons: the published surface reads end to end without the raise sites
in the way, and each piece stays inside the repository's module budget.
Why a fourth surface dataclass. LifecycleRow, AdmissionSurface and
PauseSurface each exist because a lane's rows did not fit the one before it,
and C1-K's do not fit any of the three. AdmissionSurface requires an
override_argument on a row it does not admit, which is right for a lane that
declined its triage and wrong for one that applied it -- these three rows are
refused because the recommendation was applied, not overridden.
PauseSurface has the right shape and the wrong name: it partitions the entry
points and demands a break beside every replacement, which is exactly this
lane's obligation, but a governance row filed under a pause type would be a row
whose home says something false about it. So :class:GovernanceSurface restates
PauseSurface's two invariants rather than importing them, and the restating
is deliberate: they are the invariants this lane's acceptance names, and a lane
that inherited them from a module about pauses would lose the reason it has
them. It adds one of its own -- kind -- because C1-K is the first subgroup
whose rows refuse through two different mechanisms, and a table that could not
say which would make the reader guess.
GovernanceSurface
dataclass
¶
GovernanceSurface(path: str, subgroup: str, owner: str, kind: str, disposition: str, served_by: tuple[str, ...], refused_by: tuple[str, ...], inert_on: tuple[str, ...], consumer: str, observable: str, replaced_by: str | None = None, adopter_break: str | None = None, override_argument: str | None = None)
One C1-K row, and what 11.0 does with it on each entry point.
served_by / refused_by / inert_on partition
:data:~symfonic.agent.cutover.lifecycle_contract.PUBLIC_ENTRY_POINTS
exactly, for the reason LifecycleRow gives: an unmeasured third entry
point is the gap that made two thirds of this programme's earlier evidence
unusable, and a row with a hole in its surface would reintroduce it as a
data structure.
replaced_by and override_argument are mutually exclusive and one is
required, so this table cannot hold a row that was neither replaced nor
argued about -- "the triage recommended REPLACE and the code is silent" is
then not a state anybody has to infer from an absence. A replaced_by
without an adopter_break is refused for the reason this lane's
acceptance gives in as many words: collapsing REPLACE into MIGRATE ships a
breaking change as a migration note.