Skip to content

symfonic.agent.cutover.diagnostics

diagnostics

Composite stock-switch diagnostic: admit/refuse per flag, never first-only.

The live envelope returns its first refusal, so a hydration refusal hides missing consolidation or routing evidence in a stock deployment. This module evaluates every :data:DEFAULT_ADMISSION_ROWS row independently and reports each flag's verdict with its reason -- admitted-by-disabled, admitted-by-served, or refused-with-cause. Operators diagnose refusals from this report instead of inferring them from which legacy body served the turn.

Pure: config and bundle in, verdicts out. It never imports platform resources; the durable side (every fallback's reason-carrying row) travels through the host-owned FallbackJournal/metrics sink the composition root wires, and is proven per switch and door in tests/agent/cutover/test_stock_diagnostics.py.

StockSwitch dataclass

StockSwitch(field: str, capability: str, admitted: bool, reason: str)

One stock flag's admission verdict, with the reason either way.

describe_stock_switches

describe_stock_switches(verdicts: tuple[StockSwitch, ...]) -> str

One line per flag: field, ADMITTED/REFUSED, and the reason.

Source code in src/symfonic/agent/cutover/diagnostics.py
def describe_stock_switches(verdicts: tuple[StockSwitch, ...]) -> str:
    """One line per flag: field, ADMITTED/REFUSED, and the reason."""
    return "\n".join(
        f"{verdict.field}: "
        f"{'ADMITTED' if verdict.admitted else 'REFUSED'} ({verdict.reason})"
        for verdict in verdicts
    )

diagnose_stock_switches

diagnose_stock_switches(config: Any, bundle: Any) -> tuple[StockSwitch, ...]

Report admit/refuse for every stock switch, in row order.

A flag that is not exactly True is admitted-by-disabled: the stock default is off, so there is nothing to refuse. A flag that is True is admitted only when the bundle serves its predicate, else refused with the predicate named. A missing bundle refuses every enabled flag.

Source code in src/symfonic/agent/cutover/diagnostics.py
def diagnose_stock_switches(
    config: Any, bundle: Any
) -> tuple[StockSwitch, ...]:
    """Report admit/refuse for every stock switch, in row order.

    A flag that is not exactly ``True`` is admitted-by-disabled: the stock
    default is off, so there is nothing to refuse. A flag that is ``True``
    is admitted only when the bundle serves its predicate, else refused with
    the predicate named. A missing bundle refuses every enabled flag.
    """
    verdicts: list[StockSwitch] = []
    for row in DEFAULT_ADMISSION_ROWS:
        enabled = getattr(config, row.field, None) is True
        if not enabled:
            verdicts.append(
                StockSwitch(
                    field=row.field,
                    capability=row.capability,
                    admitted=True,
                    reason=f"{row.field} is off in config; nothing to refuse",
                )
            )
        elif bundle is None:
            verdicts.append(
                StockSwitch(
                    field=row.field,
                    capability=row.capability,
                    admitted=False,
                    reason=f"{row.field}=True but no authorised bundle was built",
                )
            )
        elif row.is_served_by(bundle):
            verdicts.append(
                StockSwitch(
                    field=row.field,
                    capability=row.capability,
                    admitted=True,
                    reason=f"{row.field}=True and bundle.{row.bundle_predicate}() holds",
                )
            )
        else:
            verdicts.append(
                StockSwitch(
                    field=row.field,
                    capability=row.capability,
                    admitted=False,
                    reason=(
                        f"{row.field}=True but bundle.{row.bundle_predicate}() "
                        "is false"
                    ),
                )
            )
    return tuple(verdicts)