Invariants

Declarative business rules that prevent your system from entering invalid states

What are Invariants?

Invariants are business rules that must always hold. "No two users can share the same email address." "Invoice amounts must be greater than zero." "A workspace cannot have more than one active subscription." These are not validation hints — they are hard constraints. When an invariant is violated, the system rejects the operation.

By declaring invariants in YAML alongside entities and capabilities, you make your business rules visible to AI agents, the compiler, and the Change Protocol. An agent can read an invariant spec and know exactly what rule it must preserve when modifying related entities or capabilities.

InvariantSpec Structure

interface InvariantSpec {
  name: string;          // unique invariant name, e.g. "email_must_be_unique"
  description: string;   // human-readable explanation of the rule
  entity: string;        // the entity this invariant constrains
  rule: string;          // human-readable rule description
  severity: 'error' | 'warning';
  enforcement: 'runtime' | 'compile' | 'both';
}

Enforcement Modes

Each invariant declares when it is checked:

ModeWhen CheckedUse Case
runtime During capability execution, before the operation completes Data integrity rules that depend on current state (uniqueness checks, foreign key validation)
compile During sysmara compile and sysmara check Structural rules that can be verified from specs alone (field existence, type compatibility)
both At both compile time and runtime Critical rules that benefit from early detection and runtime enforcement

Severity Levels

SeverityBehavior
error Violation blocks the operation. At compile time, this prevents compilation from succeeding. At runtime, this rejects the capability execution.
warning Violation is reported but does not block the operation. Useful for rules that should eventually be enforced strictly but currently need a grace period.

How Invariants Bind to Entities

Each invariant declares the entity it constrains. This creates an enforces edge in the AI System Graph from the invariant node to the entity node. An entity can have multiple invariants, and the entity spec can also list its invariants in the invariants array for cross-referencing.

How Invariants Bind to Capabilities

Capabilities list invariants in their invariants array. This creates protects edges from the invariant to the capability. When the capability executes, the runtime checks all protecting invariants. This means a capability can be protected by invariants from different entities — for example, downgrade_subscription checks both subscription_must_have_workspace (on the subscription entity) and cannot_downgrade_with_unpaid_invoices (also on the subscription entity but involving invoice data).

YAML Example: SaaS Billing Invariants

invariants:
  - name: email_must_be_unique
    description: No two users can share the same email address
    entity: user
    rule: email must be unique across all users
    severity: error
    enforcement: runtime

  - name: workspace_must_have_owner
    description: Every workspace must be linked to a valid existing user as its owner
    entity: workspace
    rule: owner_id must reference a valid user.id
    severity: error
    enforcement: runtime

  - name: no_duplicate_active_subscription
    description: A workspace cannot have more than one active subscription at a time
    entity: subscription
    rule: workspace_id must be unique among subscriptions where status is active or trialing
    severity: error
    enforcement: runtime

  - name: invoice_amount_must_be_positive
    description: Invoice amounts must be greater than zero
    entity: invoice
    rule: amount_cents must be greater than 0
    severity: error
    enforcement: runtime

  - name: cannot_downgrade_with_unpaid_invoices
    description: A subscription cannot be downgraded if the workspace has unpaid invoices
    entity: subscription
    rule: no invoices with status open or past_due may exist for the subscription when downgrading
    severity: error
    enforcement: runtime

Graph Relationships

Invariants create two types of edges in the AI System Graph:

This dual binding lets AI agents trace invariants in both directions: "what rules constrain the user entity?" and "what rules must hold when create_user executes?"

Compiler Integration

The Capability Compiler generates test stubs for every invariant listed on a capability. Each stub is a placeholder test that reminds developers (and AI agents editing tests) that the invariant must be verified. The compiler also includes invariant details in the generated metadata JSON, so downstream tools have full context about which rules apply.

AI-Safe Change Workflows

Invariants receive special attention in the Change Protocol. When a change plan affects invariants, the plan generator automatically adds a human review flag: "Affects N invariant(s) -- verify constraints still hold." This is because invariant changes can silently weaken business rules, which is a category of error that AI agents should not make autonomously. The Change Protocol treats invariant modifications as inherently requiring human review.