Skip to content

Add Belgium pilot: Axiom rules engine over populace-be entity tables - #448

Merged
MaxGhenis merged 6 commits into
mainfrom
be-axiom-pilot
Aug 30, 2026
Merged

Add Belgium pilot: Axiom rules engine over populace-be entity tables#448
MaxGhenis merged 6 commits into
mainfrom
be-axiom-pilot

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Fixes #447

Summary

Add a Belgium pilot that connects PolicyEngine's dataset/model interfaces to the Microcosm Frame adapter and the Axiom rules engine. It executes the configured Belgian worker SSC/PIT module; it does not implement a second set of tax formulas in PolicyEngine.

  • Use microcosm.frame and AxiomEngine(..., rulespec_roots=(rulespec_root,)) with an explicit RuleSpec root. Retain the existing PopulaceBelgiumDataset public class name for compatibility.
  • Read and write person/household HDF tables with calibrated household weights as the authority. Validate redundant person weights on load, save, and already-populated in-memory runs; derive absent person weights through household membership.
  • Preserve input tables, nested metadata, and the source file. Record the dataset year separately from the executed policy period, and record the communal rate and requested outputs with each run.
  • Fingerprint the RuleSpec YAML tree, Microcosm package/adapter, Axiom wrapper/native binary, and distribution versions. Refuse runtime drift after model construction.

Validation

The approved test-only follow-up produces the current head, 910bd210e41267e02b6bc611727b04c1d72faf15:

  • The checkout-independent Belgian suite passes 15 tests and explicitly skips the one opt-in native integration test when RULESPEC_BE_ROOT points to an absent path.
  • A compatible real source stack passes 16 tests with no skips: Microcosm ba73e2f43c6f1dcb3533faeab26ecc18260bd712, Axiom bb4b5684870547756078a62f1866a77c5b56f7f3, and RuleSpec-BE b105e2b3a3086ddd2de447d58a9b951346870dd1, with CPython 3.14.4 and the native extension.
  • Ruff lint and format checks pass for the changed test file. Targeted mypy passes for all three Belgian source files, and the full PR diff passes the whitespace check.
  • Independent verification returned CLEAN for both approved test corrections. The earlier independent review also confirmed the in-memory weight repair and the household-weight authority across valid and invalid inputs.

The follow-up commit changes only tests/test_be_axiom_pilot.py. Controlled-runtime tests now create and explicitly receive a temporary RuleSpec root. The native test checks the signed net-tax contract encoded by the pinned companion fixture: the refundable work-bonus credit can make the selected PIT output negative at low remuneration. It retains finite-result, zero-income, ordering, content-identity, provenance, weight, period, and non-mutation checks. The production RuleSpec file-existence check, runtime code, and tax formulas remain unchanged.

Remaining gate and scope

Keep this PR draft for review. The refreshed CI run completed successfully: all 12 checks passed at current head 910bd210e41267e02b6bc611727b04c1d72faf15.

The pinned RuleSpec output definition and companion fixture establish the tested negative net-tax behavior within this software model. They do not independently validate Belgian law.

This pilot is outside the certified-release path. These checks do not certify Belgian population data, fiscal estimates, legal coverage, or EUROMOD parity. The follow-up adds no calibration targets, dependencies, lockfile changes, RuleSpec changes, formulas, datasets, or publication actions.

@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Rebased onto current main (e5a56a3, 2026-08-14) — the branch had drifted six weeks. Compat commit 2bde0b0:

  • policyengine.core.dataset / policyengine.core.tax_benefit_model_version deep imports → the public policyengine.core exports.
  • Explicit filepath is None guards before HDF5 read/write (Dataset.filepath is now Optional).
  • __init__(**kwargs: Any) typing; still py3.9-style Optional[]/Union[].
  • Design preserved: AxiomBelgiumPilot subclasses raw TaxBenefitModelVersion, deliberately outside certified-release pin machinery (smoke: direct_base=TaxBenefitModelVersion, release_manifest=None).
  • changelog.d/447.added.md intact.

Checks: make format / make lint pass; Belgium tests 2 collected, 2 expected skips (no source deps in CI); Belgium-scoped mypy clean. Repo-wide mypy has 126 pre-existing errors in 36 non-Belgium files — not this PR's.

Still a pilot, still deliberately not for merge as-is; refreshed so it runs against today's core ahead of the CAPE/BEAMM Brussels sessions (8/24) where it's the integration-surface demo. Note: rulespec-be#118 (couple PIT pipeline fix) is in flight and will change the worker→couple composition this pilot points at once merged.

MaxGhenis and others added 5 commits August 29, 2026 21:34
The first non-policyengine-core country channel: an Axiom-backed
TaxBenefitModelVersion outside the certified-release machinery, running
the rulespec-be composed worker pipeline (employee SSC and PIT before
withholding) over populace-be person/household tables with calibrated
weights. Includes a populace-style two-entity dataset class, a population
example scored against ONSS/SPF facts, and tests that skip cleanly when
the source-only dependencies are absent.

Fixes #447

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The composed pipeline now computes the ONSS work-bonus amounts from law
(the a/b supplied inputs are gone; the reference-wage input bridges 0 to
worker remuneration), and the ordinary-contribution concept nets the
bonus. Update the supplied defaults, exercise the phase-out in the test
fixture (wiped at 20k, partial at 30k, statutory 13.07 percent by 60k),
and label the example aggregates accordingly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Keep the shared household-weight validator authoritative on the populated-data path. Refs #447.
@MaxGhenis

MaxGhenis commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the approved in-memory weight finding (C1) in 521a66b60b1935b5cefb93c790c2a39e7ec7dc95.

AxiomBelgiumPilot.run() now always invokes the existing household-weight validator, including when the dataset already contains in-memory tables. Absent redundant person weights are derived from household membership; matching copies are accepted and mismatches fail before Axiom execution. Regressions were added first and demonstrated the failure before the repair. The prior HDF, provenance, and run-configuration fixes remain intact.

Validation before and after rebasing onto main 1e4d2493a9ffcf7d9e72e70864c921a64e933ab5:

  • Belgian pilot test file: 15 passed, 1 explicit native-Axiom integration skip.
  • make format/make lint, targeted mypy (3 source files), and whitespace checks pass; formatting changed no files.
  • Independent verification is CLEAN, including three valid in-memory executions and ten invalid-input refusals.
  • All five feature patches are unchanged by the rebase; the resulting source tree is identical to the reviewed pre-rebase tree.

The push used an exact expected-head lease against the actual PR repository/branch. The PR description now states the Microcosm API and observed checks.

A subsequent isolated run with real Microcosm ba73e2f, Axiom bb4b5684, and RuleSpec-BE b105e2b3 executed all 16 Belgian tests: 15 passed, 1 failed, 0 skipped. Native compilation/materialization succeeded, but the universal nonnegative-PIT assertion failed at €20,000 earnings. The selected net-tax output intentionally subtracts an encoded refundable work-bonus credit; the pinned model already has a negative-PIT regression. The additional test-only correction is awaiting approval, not applied. No model result has been clamped or tax formula changed.

The refreshed CI run has now completed with ten green checks and two failed Python test jobs. Each test job reports 7 failed, 816 passed, 4 skipped: seven deterministic Belgian tests still depend on a developer-local RuleSpec checkout despite their runtime/provenance mocks. This is separate from the native sign test, which is skipped in CI. A self-contained temporary test-fixture correction is proposed; the production file-existence check will not be weakened. Both additional test-only fixes are awaiting approval.

The PR remains draft until the real-stack test and refreshed CI pass. These checks do not establish legal/parity validation or population certification.

@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Approved S2/S3 test-only follow-up

Pushed 910bd210e41267e02b6bc611727b04c1d72faf15, which changes only tests/test_be_axiom_pilot.py. The checkout-independent suite passes 15 tests with the explicit native test skipped; the compatible real Axiom source stack passes 16 tests with no skips. Independent verification returned CLEAN, and the production RuleSpec existence check, runtime, and tax formulas remain unchanged.

Refreshed CI is running with no failures at this update. The PR remains draft pending completion.

@MaxGhenis
MaxGhenis marked this pull request as ready for review August 30, 2026 11:36
@MaxGhenis
MaxGhenis merged commit 31dfa02 into main Aug 30, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Belgium pilot: run the Axiom rules engine over populace-be entity tables

1 participant