Skip to content

symfonic.agent.cutover.admission_surfaces

admission_surfaces

Which surface honours an admitted row, and which one does not (TA8.44).

TA8.41 published :mod:~symfonic.agent.cutover.lifecycle_contract for rows whose whole story fits inside the three public entry points. This lane's six rows do not fit there, and the misfit is the finding rather than an inconvenience:

  • agent.max_agent_depth and model_pricing_overrides are served on the turn, like every row LIFECYCLE_ROWS holds.
  • scheduler is served by a public surface that is not an entry point -- SymfonicAgent.flush_background_tasks -- so a contract that could only say "served / refused / inert" per entry point would have to call it inert everywhere and lose the reader entirely.
  • self_reflection and reflection_prompt are inert on every surface because another field is refused, and that coupling is the entire licence for admitting them. A contract with nowhere to write it down would leave the licence in a comment, where nothing fails when it expires.
  • role_model_resolver is not admitted, and this module says so by name with its argument attached, so "the triage recommended MIGRATE and the code is silent" cannot be the state anybody has to infer from an absence.

So :class:AdmissionSurface adds two things to LifecycleRow's three dispositions: off_turn_surface, the file::symbol that reads the value when no entry point does, and inert_because, the refusal an inert admission rides on. Exactly one of them must be present when nothing serves the row on a turn -- enforced in __post_init__, because "a value threaded to nothing" is the defect TA8.19 found for session_id, and a data structure that permits it invites it back.

The rule this module exists to make un-forgettable: an admitted field with no consumer on an entry point is a silent drop unless the contract names what does consume it, or names the refusal that makes it unreachable on both routes.

AdmissionSurface dataclass

AdmissionSurface(path: str, subgroup: str, owner: str, admitted: bool, disposition: str, served_by: tuple[str, ...], refused_by: tuple[str, ...], inert_on: tuple[str, ...], consumer: str, observable: str, off_turn_surface: str | None = None, inert_because: str | None = None, override_argument: str | None = None)

One TA8.44 row, and the surface that actually honours it.

served_by / refused_by / inert_on partition :data:PUBLIC_ENTRY_POINTS exactly, for the reason :class:~symfonic.agent.cutover.lifecycle_contract.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.

admitted is a separate field from all of that, and it is separate deliberately. A row can be refused-to-legacy by the default-deny envelope while its consumers are perfectly real -- that is what every MISSING CONTRACT row in the inventory is -- and recording it here with admitted=False keeps the argument next to the field instead of in a document nothing checks.

surfaces_for_subgroup

surfaces_for_subgroup(subgroup: str) -> tuple[AdmissionSurface, ...]

Every row of one TA8.25 subgroup, in declaration order.

Parity is asserted per field and never aggregated across the lane, so the tests read the lane one subgroup at a time rather than iterating the whole mapping and reporting a single verdict.

Source code in src/symfonic/agent/cutover/admission_surfaces.py
def surfaces_for_subgroup(subgroup: str) -> tuple[AdmissionSurface, ...]:
    """Every row of one TA8.25 subgroup, in declaration order.

    Parity is asserted per field and never aggregated across the lane, so the
    tests read the lane one subgroup at a time rather than iterating the whole
    mapping and reporting a single verdict.
    """
    return tuple(
        surface
        for surface in ADMISSION_SURFACES.values()
        if surface.subgroup == subgroup
    )