Skip to content

symfonic.capabilities.governance.context

context

What governance judges, and what it knows while judging (T3.4.4).

The subject is immutable: a stage that amends it returns a new one, so "what did the scrubber actually change?" is answerable by comparing two values rather than by trusting a mutation log. The context is mutable and deliberately thin — it carries the run's identity, the enforcement knob, and exactly one published reading (the intent verdict) that a later stage is contractually allowed to consume.

GovernanceContext dataclass

GovernanceContext(run_id: str = '', scope_path: tuple[str, ...] = (), enforcement: Enforcement = Enforcement.ENFORCE, intent: IntentReading | None = None, metadata: dict[str, Any] = dict())

Ambient facts for one governed turn.

intent starts empty and is filled by the intent stage. A stage reading it before that stage has run reads None — which is the withheld claim, not "no action intended".

GovernanceSubject dataclass

GovernanceSubject(query: str = '', draft: str = '', pinned: str = '', grounding: str = '', properties: Mapping[str, Any] = dict(), tool_calls: tuple[ToolCall, ...] = (), confidence: float | None = None)

The turn, as governance sees it.

pinned is the portion of the payload that may never be dropped to make room — boundaries, operator instructions, the safety preamble. Budgeting refuses rather than trims it (T3.2.1's rule: a prompt missing its boundaries is worse than a prompt that refused to build).

with_properties

with_properties(properties: Mapping[str, Any]) -> GovernanceSubject

A subject carrying these properties, which the result cannot edit.

A proxy rather than dict(...). Several stages read one subject's properties in a turn, and a stage handed a mutable bag could rewrite what a later stage sees -- a side channel around the pipeline, whose whole shape is "a stage says what it decided by returning a verdict".

Source code in src/symfonic/capabilities/governance/context.py
def with_properties(self, properties: Mapping[str, Any]) -> GovernanceSubject:
    """A subject carrying these properties, which the result cannot edit.

    A proxy rather than ``dict(...)``. Several stages read one subject's
    properties in a turn, and a stage handed a mutable bag could rewrite
    what a later stage sees -- a side channel around the pipeline, whose
    whole shape is "a stage says what it decided by *returning* a verdict".
    """
    return replace(self, properties=MappingProxyType(dict(properties)))