Skip to content

Implement an Axiom-backed RulesEngine adapter #260

Description

@MaxGhenis

Part of #259 (populace-be epic).

What

Implement the first non-PolicyEngine RulesEngine adapter: populace.frame.adapters.axiom, wrapping the Axiom rules engine runtime for the Belgian rule set. The protocol (packages/populace-frame/src/populace/frame/rules.py) is deliberately minimal:

  • variable_metadata(name) -> VariableMetadata — owning entity, dtype kind, period semantics
  • variables() -> Sequence[str] — input variables the engine accepts on a dataset (computed/formula-owned outputs excluded)
  • entity_schema() -> EntitySchema — the engine's entity structure
  • materialize(bundle, variables, period) -> Mapping[str, np.ndarray] — compute variables, row-aligned to each variable's entity table
  • export_contract() -> ExportContract — the column-parity contract exports are gated against
  • write_dataset(...) — write a Frame as an engine-native dataset

Reference implementation: packages/populace-frame/src/populace/frame/adapters/policyengine_us.py.

Provide-side counterpart: the Axiom runtime must expose a vectorized surface for this (tracked in TheAxiomFoundation/axiom-rules-engine — linked from the epic). Coordinate the two so the adapter stays thin.

Design decisions this issue must make

  1. Engine-native dataset format for BE. There is no policyengine-be package, so the adapter itself owns the export contract — propose entity-table H5 matching the US/UK layout so populace.data loaders generalize.
  2. Entity mapping. Belgian PIT is largely individual with household-level elements and regional surcharges; benefits use household/family units. entity_schema() must express the units the Axiom BE encodings define; document the mapping from SILC household/person structure.
  3. Formula-owned boundary. The formula-owned-export lesson from the US (frozen engine-computed columns mask reforms) applies from day one: the export contract must classify computed vs input variables so the gate works.
  4. Reform materialization. The protocol notes reform/branch simulation as a planned breaking extension (materialize(..., reform=...) or sibling). The BE validation oracle needs counterfactual runs — either land the protocol extension here or sequence the oracle work behind it. State the choice explicitly.

Acceptance

  • Behavioral contract tests parameterized over adapters pass for the Axiom adapter wherever semantics overlap with the policyengine-us adapter (metadata resolution, entity alignment, materialize row-alignment, export contract shape).
  • Smoke test: materialize the pilot-slice PIT variables for a toy Frame and reproduce hand-computed values for 2–3 example households.
  • Nothing outside the adapter imports the Axiom engine.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions