Skip to content

symfonic.capabilities.governance.ordering

ordering

Ordering mechanics: a rulebook is an order plus two declarations (T3.4.4).

A RuleBook is an immutable, totally-ordered list of StageRule. It answers three questions and refuses everything else:

  • what rank does this stage hold?
  • does this composition respect the order?
  • what does this stage declare — its phase, its failure mode, and why?

Extension is a new rulebook, never a mutation of the shared one, so an adopter adding a stage cannot reorder governance for everyone else in the process.

RuleBook

RuleBook(rules: Iterable[StageRule])

An ordered, immutable set of stage declarations.

Source code in src/symfonic/capabilities/governance/ordering.py
def __init__(self, rules: Iterable[StageRule]) -> None:
    ordered = tuple(rules)
    seen: dict[str, StageRule] = {}
    previous = -1
    for rule in ordered:
        if rule.name in seen:
            raise StageOrderError(f"stage {rule.name!r} is declared twice")
        rank = PHASE_RANK[rule.phase]
        if rank < previous:
            raise StageOrderError(
                f"stage {rule.name!r} declares phase {rule.phase} after a later "
                "phase; phases may not run backwards",
            )
        previous = rank
        seen[rule.name] = rule
    self._rules = ordered
    self._by_name = seen

extend

extend(rule: StageRule, *, after: str | None = None) -> RuleBook

Return a new rulebook with rule inserted after after.

after=None appends. The result is validated by the constructor, so a phase inversion is refused here rather than at the first turn.

Source code in src/symfonic/capabilities/governance/ordering.py
def extend(self, rule: StageRule, *, after: str | None = None) -> RuleBook:
    """Return a new rulebook with ``rule`` inserted after ``after``.

    ``after=None`` appends. The result is validated by the constructor,
    so a phase inversion is refused here rather than at the first turn.
    """
    if rule.name in self._by_name:
        raise StageOrderError(f"stage {rule.name!r} is already declared")
    if after is None:
        return RuleBook((*self._rules, rule))
    index = self.rank_of(after)
    return RuleBook(
        (*self._rules[: index + 1], rule, *self._rules[index + 1 :]),
    )

validate

validate(stages: Sequence[str]) -> None

Refuse a composition that is not a subsequence of this order.

Source code in src/symfonic/capabilities/governance/ordering.py
def validate(self, stages: Sequence[str]) -> None:
    """Refuse a composition that is not a subsequence of this order."""
    seen: set[str] = set()
    previous = -1
    for name in stages:
        rank = self.rank_of(name)
        if name in seen:
            raise StageOrderError(f"stage {name!r} appears twice in the pipeline")
        if rank <= previous:
            raise StageOrderError(
                f"stage {name!r} is composed after {self.names[previous]!r}; the "
                f"declared order is {' -> '.join(self.names)}",
            )
        seen.add(name)
        previous = rank

StageRule dataclass

StageRule(name: str, phase: GovernancePhase, failure_mode: FailureMode, rationale: str)

One stage's declaration: where it runs, and what a failure means.

rationale is required and is checked for being a sentence rather than a label. A failure mode without a stated reason is a coin flip somebody will later "optimise" in the wrong direction.