From baf68df5434715db56a7b2093f9cc14c36cea7e8 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 28 Jun 2026 09:57:23 -0400 Subject: [PATCH] Label firm link support experimental --- DESIGN.md | 8 +++++--- README.md | 5 +++++ packages/populace-frame/README.md | 6 +++--- packages/populace-frame/src/populace/frame/schema.py | 10 ++++++---- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index 88fcaf5..6a5e176 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -59,13 +59,15 @@ and the thing weights refer back to, made executable. Holds: `synthetic_conditional`, `tail_verbatim`, ...). Pool design is explicit survey design: oversample where support is scarce, carry the weights that make mass honest. Calibration owns representation; generation owns support. -- **Links** (documented placeholder today): `LinkSpec` declares many-to-many +- **Links** (experimental placeholder today): `LinkSpec` declares many-to-many associations between entities — a `jobs` link between persons and firms, a policy link between persons and plans — carried as their own tables, keyed by link name and validated against the linked tables' ids. Partition membership stays the group-entity system; links are for relations that - don't partition. The full link operator (link-aware broadcast / select / - concat, link targets outside the partition entities) comes later. + don't partition. Firm tables and person-firm links are valid experimental + frames, not production firm microsimulation support. The full link operator + (link-aware broadcast / select / concat, link targets outside the partition + entities) comes later. - **Variable metadata**: name → entity, dtype, period semantics — resolved through the RulesEngine protocol, never guessed per-tool. - **Weighted accounting** as methods (`sum`, `mean`, `quantile`, `gini`, diff --git a/README.md b/README.md index 924f979..52725cf 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,11 @@ will pin the constellation. | `populace-build` | `populace.build` | population build plans, donor graphs, release gates, and country build stages | one-off build drivers | | `populace-data` | `populace.data` | published population registry and lazy engine loaders | country-specific data packages | +Firm support is **experimental**. The frame kernel can declare firm entity +tables and validate person-firm `jobs` link tables, but link-aware operators, +firm calibration targets, and firm release pipelines are not production +surfaces yet. + See [DESIGN.md](DESIGN.md) for the charter: why the rebuild, the kernel semantics, the RulesEngine protocol (policyengine-us today, Axiom rulespec-us next), longitudinal design (one weight per trajectory), and the process rules diff --git a/packages/populace-frame/README.md b/packages/populace-frame/README.md index fc92e2a..932ab23 100644 --- a/packages/populace-frame/README.md +++ b/packages/populace-frame/README.md @@ -15,10 +15,10 @@ no operator ever re-derives structure or silently corrupts weights: (design → importance → calibrated), and can be held to mass conservation. - **Strata**: per-person provenance labels, so pool design is explicit survey design. -- **Links** (documented placeholder): `LinkSpec` declares many-to-many +- **Links** (experimental placeholder): `LinkSpec` declares many-to-many associations between entities (e.g. a `jobs` link between persons and - firms); the frame validates link tables on construction. The full link - operator comes later. + firms); the frame validates link tables on construction. Firm tables and + person-firm links are experimental, and the full link operator comes later. - **Weighted accounting** (`wsum`, `wmean`, `wquantile`, `wmedian`, `gini`, `groupby_wsum`) computed on the frame. - **US unit structure**: `assign_us_unit_structure` builds the PolicyEngine diff --git a/packages/populace-frame/src/populace/frame/schema.py b/packages/populace-frame/src/populace/frame/schema.py index d028e95..72db5c8 100644 --- a/packages/populace-frame/src/populace/frame/schema.py +++ b/packages/populace-frame/src/populace/frame/schema.py @@ -9,8 +9,8 @@ :class:`LinkSpec` declares an *association* between two entities (e.g. a ``jobs`` link between persons and firms): a many-to-many relation carried as its own table, distinct from the partition semantics of group membership. -Links are a documented placeholder today — the schema declares them and the -frame validates their tables, but link-aware operators come later. +Links are an experimental placeholder today — the schema declares them and +the frame validates their tables, but link-aware operators come later. :class:`VariableMetadata` records what a variable is (owning entity, dtype kind, period semantics) so tools resolve it through metadata instead of @@ -36,10 +36,12 @@ class LinkSpec: entities' id columns (``{left}_id`` / ``{right}_id`` per the schema's id-column convention), each validated against the linked table's ids. - This is a documented placeholder: the schema declares links and the + This is an experimental placeholder: the schema declares links and the frame validates their tables on construction, but link-aware operators (broadcast through links, link-preserving ``select``/``concat``, - link targets outside the partition entities) come later. + link targets outside the partition entities) come later. Person-firm + links are valid experimental frames, not production firm microsimulation + support. Attributes: name: Name of the link (and of its table in a frame's ``tables``).