Skip to content
Merged
9 changes: 9 additions & 0 deletions changelog.d/1183-reporting-classifiers.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Add spec-declared benefit-unit income deciles and receipt groups, including
weighted stable-ID ties, assigned before-tax benefit income, mixed-unit counts,
and typed baseline cells carried across scenario branches. Declare the NZ A1/A2
parameters and shared MC11 superannuitant predicate; refuse unavailable gross
main-benefit and Veterans Pension inputs. Midpoint labels use exact integer
arithmetic on the represented float64 weights, preserving exact boundaries and
power-of-two scaling. Clones remain distinct reporting units and may occupy
different cells. Method provenance resolves to a repository document. Production
graph wiring remains G8-w.
119 changes: 119 additions & 0 deletions docs/nz-reporting-classifiers-method.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# New Zealand reporting classifier method

The reporting population contains one row per benefit unit. The declared cells
are income decile × family type and the three receipt groups. The classifier
parameters live in
[reporting_classifiers.json](../packages/microcosm-build/src/microcosm/build/nz/reporting_classifiers.json).
This document records the method basis and the checks needed before activation.

## A1 Income decile (provisional)

The provisional stratifier is annual gross benefit-unit income for TY2026–27,
before income tax, Accommodation Supplement, and Working for Families. It
includes market income and paid main-benefit, New Zealand Superannuation, and
Veterans Pension amounts. Including benefit income avoids ranking all units
with no market income as one zero-income tie; excluding Accommodation Supplement
keeps the reported outcome out of its own stratifier. Equivalised disposable
income is a defensible alternative that would change the reporting cells, so
the gross-income basis still needs confirmation before publication.

Market components are employment, nonfarm and farm self-employment, interest,
dividend, rental, and private-pension income. Annual market amounts use an
annualisation factor of one. Benefit income is the assigned receipt flag
multiplied by the engine's before-tax weekly paid amount after its income test,
then multiplied by 52. Entitlement does not substitute for assigned receipt.
All components must use the same before-tax basis. A net paid amount or a gross
maximum rate does not establish the required before-tax paid amount.

The current declaration leaves unavailable before-tax main-benefit and Veterans
Pension paid amount columns null and refuses activation. Veterans Pension
receipt must also be present: a missing flag cannot mean no receipt. Rental
income is after business expenses, and the before-tax interpretation of rental
and private-pension inputs must be verified before activation.

Each benefit unit uses its calibrated weight. The transport declaration selects
the household calibrated-weight carrier and associates its weight with each
unit. Units are sorted by gross income, then by a unique stable unit identifier.
The identifier must survive rebuilds of the same pinned donor and unit rule;
shared source-household lineage does not merge units. Clones remain distinct
reporting units and can land in different cells, including when they have equal
income and weight.

The declared rank convention is the cumulative-weight midpoint. With preceding
weight `P`, unit weight `w`, total weight `W`, and `n` bins, the label is
`min(floor(n * (2 * P + w) / (2 * W)) + 1, n)`. Bins are left-closed: exact
equality with boundary `k/n` enters bin `k + 1`. No unit is split between bins.
Zero-weight units use the cumulative mass at their sorted position; rank one
is clipped into the final bin. An all-zero population is refused. The midpoint
convention makes A1's tie and boundary rule precise and remains provisional.

Each supplied float64 weight is an exact dyadic rational. Expressing weights as
integer numerators over a common power-of-two denominator makes prefix sums and
the midpoint division exact. This determines labels without cumulative floating
point error or a boundary tolerance. A common power-of-two scaling with exactly
representable float64 results preserves every label. Weighted shares are reported
separately using the scenario's weights and need not be exactly one tenth per cell.

The central scenario S0 supplies the baseline cells. Entitlement scenarios
branch after calibration, so their units, weights, and stratifying incomes are
the same. Calibration variants may change weights, and the receipt variant may
change income; each variant carries S0's cell by stable unit identifier. The
weighted share of every fixed cell must be reported for every scenario and
variant. These fixed memberships preserve comparisons even when variant cells
are no longer weighted tenths.

The disclosure on New Zealand Superannuation remains material: the current
shared-residence input defaults false, overstating payments to single people
who share a home and moving those units upward in the income ranking.

## A2 Receipt group

The legal basis is the Social Security Regulations 2018 (LI 2018/202), read for
this method as at 5 April 2026. The text read is the PCO XML pinned in
`TheAxiomFoundation/axiom-corpus` release `nz-rulespec-2026-07-25`, at
`data/corpus/sources/nz/regulation/2026-06-16-rulespec-nz-pco/regulation/public/2018/0202/wholeof.xml`
(sha256 `5f1250b903ce1b618eebd6370d6db8c51cb377b9fdb5cf4d171e259cd0e85d8f`). The
legislation.govt.nz links below open the latest version. [Regulation 17, PCO
LMS96264](https://www.legislation.govt.nz/regulation/public/2018/0202/latest/LMS96264.html)
defines a beneficiary by payment of a main benefit, New Zealand Superannuation,
or a veteran's pension. Everyone else is a non-beneficiary for that regulation.
The base-rate rules in regulation 17(2) depend on the applicant's benefit and,
for a couple, include a spouse or partner component.

[Regulation 18, PCO
LMS96265](https://www.legislation.govt.nz/regulation/public/2018/0202/latest/LMS96265.html)
applies its income reduction only to a non-beneficiary as defined in regulation
17. It reduces the assessed amount by 25 cents for each dollar of relevant
weekly income above the applicable threshold. A recipient applicant receiving
New Zealand Superannuation or a veteran's pension therefore does not fall under
that non-beneficiary reduction.

The three-way reporting split is a reporting convention. The legal definition
includes both main-benefit and pension recipients as beneficiaries, and the
base-rate provisions depend on the applicant; they do not establish a priority
between partners in a mixed receipt unit. The reporting convention assigns:

1. `superannuitant` if any member has assigned New Zealand Superannuation or
Veterans Pension receipt;
2. otherwise `beneficiary` if any member has assigned main-benefit receipt;
3. otherwise `other`.

The current main-benefit predicates name Jobseeker Support, Sole Parent Support,
and Supported Living Payment. The priority order, default group, membership
columns, and receipt predicates are spec parameters. Every required assigned
receipt flag must be present and boolean; missing Veterans Pension support must
be reported and refused rather than assumed false. Each scenario reports the
count of units satisfying multiple receipt predicates.

The S0–S4 Accommodation Supplement exclusion selects the same superannuitant
predicate as the reporting classifier. Their excluded units must equal the
`superannuitant` reporting group. That group's Accommodation Supplement cells
are structural zeros in those scenarios and belong in the gate's declared
structural-zero list; actual zero diagnostics still depend on reported amounts.

The Accommodation Supplement non-beneficiary input also needs a receipt audit.
For an applicant receiving New Zealand Superannuation or Veterans Pension it
must be false under regulation 17(1). The current any-member receipt binding
includes New Zealand Superannuation and the supported main benefits but requires
extension when Veterans Pension receipt becomes available. This audit checks the
legal payment distinction separately from the reporting group's priority rule.
67 changes: 67 additions & 0 deletions docs/transport-entitlement.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,73 @@ does not accept an `aging_index` parameter. If pre-calibration quantile maps are
aged too, those variants must branch from CREATE. V3 declares its receipt
override before its independent problem and calibration.

Reporting classifiers are available as three declarative kernels:
`reporting.income_decile@1`, `reporting.carry_income_decile@1`, and
`reporting.receipt_group@1`. Their `classifier` parameter is canonical JSON,
with a resource `classifier_sha256` and a `scenario` label. Income kernels
also declare `entities`, person first, including the reporting entity and
the stored weight entity. They reconstruct the Frame and resolve the unit's
inherited weights; the declared weight kind is checked. Every kernel owns
exactly one all-row classifier column: `income_decile` as `int64`, or
`receipt_group` as `string`.

The baseline income kernel runs only for `boundary_scenario`. Declared market
and benefit components must be before tax. Benefit components multiply the
engine payment by assigned boolean receipt and their annualisation factor;
missing flags, net components and explicitly excluded outcome columns refuse.
Member amounts sum in stable person-ID order. Income ties sort by the declared
unique tie key. The provisional `weighted_midpoint` convention assigns a unit
at cumulative weight before it plus half its own weight; an exact boundary
enters the higher decile. Zero-weight units have deterministic labels and no
weighted mass. A single positive-weight unit enters decile 6 with ten bins;
an all-zero population refuses. Each receipt reports all decile weighted shares.
Each finite float64 weight is represented as an exact dyadic rational. The
classifier converts these to integer weights at a common power-of-two
denominator and uses exact integer prefix sums and division to decide labels.
There is no boundary tolerance: a midpoint below a boundary stays below it.
Multiplying every weight by a power of two preserves all labels when the
scaling remains finite and exact (without underflow). Other floating-point
scalings can round individual weights and change their relative mass; labels
then follow the exact represented inputs. Published shares still use the
existing floating-point share calculation.

The baseline node declares `baseline_cells` with nominal type
`microcosm.reporting.income-cells`, version 1. Variant nodes consume it through
an ordinary typed artifact edge naming the baseline producer, for example:

```json
{"name": "baseline_cells", "producer": "baseline.income", "artifact": "baseline_cells"}
```

Typed artifact edges already support different populations. The carry kernel
checks the baseline scenario, classifier digest, entity, ID column, bin count,
and exact unit-ID set, then joins the saved labels by ID. It reads no income
amounts and reports weighted shares under the variant's weights. This preserves
baseline cells when calibration or assigned receipt changes. Wiring these
kernels into the production graph is the separate G8-w package.

Receipt predicates name assigned person flag columns and an any-member
reduction. All flags must be nonmissing booleans. The declared priority selects
the first matching group; the default handles unmatched units. Scenario receipts
include `mixed_units`, predicate counts and group counts. A mixed unit matches
more than one predicate, regardless of which member receives each programme.

`nz/reporting_classifiers.json` records A1/A2 parameters and provenance in the
[reporting method](nz-reporting-classifiers-method.md).
Its superannuitant predicate is also referenced by MC11 in `as_rate_bridge.json`.
The cell-support gate entry explicitly lists the S0–S4 superannuitant structural
zeros in its notes, and the classifier resource records them as data. The gate
continues to identify actual structural zeros from the measured amounts.
The income declaration deliberately refuses unresolved before-tax main-benefit
and Veterans Pension payment columns. The current bindings request net weekly
main-benefit payments and a separate gross Jobseeker rate; the bindings do not
declare a verified before-tax paid amount. The assigned Veterans Pension flag is also
unsupported in the current closure and must be supplied before classification.
Family IDs used for ties are deterministic head-person IDs for the same pinned
donor and unit rule; source-household keys shared by clones do not replace them.
Clones remain distinct reporting units and may occupy different cells, including
when their incomes and weights are equal.

Engine components and masks can declare an NZS/VP alternative; an explicit
exclusion input and counted excluded-unit reference can declare the fallback.
The toy tests exercise these declaration and grouping shapes with invented
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,20 @@
"superannuitant_units": {
"central": "exclude_and_count",
"scenario_s5": "reg17_superannuitant_base_rate",
"status": "The harness has no NZ Superannuation or Veteran's Pension base-rate branch. G7 implements one from the reg 17 text if it can; otherwise the MC11 fallback stands: superannuitant units are excluded from the central run and counted. Scenario S5 carries the alternative. Awaiting D1 (MC11)."
"status": "The harness has no NZ Superannuation or Veteran's Pension base-rate branch. G7 implements one from the reg 17 text if it can; otherwise the MC11 fallback stands: superannuitant units are excluded from the central run and counted. Scenario S5 carries the alternative. Awaiting D1 (MC11).",
"predicate": {
"resource": "reporting_classifiers",
"path": [
"receipt_group",
"predicates",
"superannuitant"
]
},
"predicate_citation": {
"item": "A2",
"source": "docs/nz-reporting-classifiers-method.md#a2-receipt-group"
},
"predicate_note": "MC11 exclude-and-count and reporting must select this one assigned-member receipt predicate. A bridge implementation must resolve the reference rather than infer superannuitants from entitlement or age."
},
"beneficiary_note": "The harness computes the base rate from zero-income Jobseeker Support for every scenario, beneficiary or not; accommodation_supplement_non_beneficiary itself comes from the receipt layer through the group encode, not from this bridge.",
"differential_expectations": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@
"kind": "legacy_json",
"schema_id": "legacy_json"
},
{
"path": "reporting_classifiers.json",
"kind": "legacy_json",
"schema_id": "legacy_json"
},
{
"path": "scenarios.json",
"kind": "legacy_json",
Expand Down
2 changes: 1 addition & 1 deletion packages/microcosm-build/src/microcosm/build/nz/gates.json
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@
"target_maximum_single_donor_dollar_share": 0.05
},
"evidence_absent_blocks": true,
"notes": "MC15: missing, malformed or scenario-incomplete source-household diagnostics block. Cells below ESS 100, above contribution CV 2 or donor dollar share 10% are suppressed, never reported; properly suppressed cells do not block. Structural-zero cells are listed separately. Subgroup rows report entitlement, without invented subgroup payment comparators."
"notes": "MC15: missing, malformed or scenario-incomplete source-household diagnostics block. Cells below ESS 100, above contribution CV 2 or donor dollar share 10% are suppressed, never reported; properly suppressed cells do not block. Structural-zero cells are listed separately. Subgroup rows report entitlement, without invented subgroup payment comparators. G8 addendum A2 explicitly expects structural-zero cells: S0/beneficiary_superannuitant_other/superannuitant, S1/beneficiary_superannuitant_other/superannuitant, S2/beneficiary_superannuitant_other/superannuitant, S3/beneficiary_superannuitant_other/superannuitant, S4/beneficiary_superannuitant_other/superannuitant. The machine-readable list is reporting_classifiers.json structural_zero_cells; actual structural-zero diagnostics are derived from reported amounts."
},
{
"id": "weight_effective_sample_size_target_a",
Expand Down
Loading
Loading