Skip to content

Add NZ reporting classifiers: income deciles and receipt groups (G8-p) - #1234

Merged
MaxGhenis merged 7 commits into
mainfrom
nzhub/g8p-classifiers
Oct 13, 2026
Merged

MaxGhenis merged 7 commits into
mainfrom
nzhub/g8p-classifiers

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Adds the NZ reporting classifiers the graph reports by: income decile (A1) and receipt group (A2), carried from the baseline into every scenario branch by stable unit id. This is package G8-p of #1183. The production graph wiring is G8-w; here only toy graphs wire complete branches.

What it adds

Shared, country-neutral code:

  • microcosm/frame/reporting.py:
    • strict executable declarations (:63);
    • annual before-tax income = assigned receipt × engine amount × annualisation (:280);
    • weighted-midpoint income cells that sort by stable id, handle zero weights and publish shares. Each unit's cell is decided exactly: every float64 weight is a dyadic rational, so the cumulative sums and the midpoint-vs-boundary comparisons are done in exact integer arithmetic, with no float tolerance (d3827c0);
    • baseline joins by unit id (:370);
    • priority receipt groups with mixed counts (:391).
  • build/transport/reporting_kernels.py:
    • a baseline producer (:195), typed baseline carry (:247) and a receipt producer (:290);
    • source weights resolved to units (:152);
    • artifact-schema and exact id-set checks refuse drift;
    • numeric scope platform_bitwise (:175).
  • artifact_types.py:40 adds the nominal income-cells type; registry.py:384 registers the producers; entitlement.py:68 admits declarative reporting nodes.

NZ spec, build/nz/reporting_classifiers.json:

  • A1 income: the calibrated weight source, tie key, S0 boundary and annualisation (:6).
  • A2: priority, default and predicates (:139).
  • Scenario carry (:169).
  • Every executable value carries provenance from the G8 method addendum (:312).
  • as_rate_bridge.json:422 (MC11) now references this resource's single superannuitant predicate.
  • gates.json:235 lists the S0–S4 superannuitant structural zeros in the cell-support notes; the resource also has machine-readable rows.
  • country_package.json:101 registers the resource.

Open items (fail closed, disclosed)

  • Before-tax paid amounts for Jobseeker Support, Sole Parent Support and Supported Living Payment are deliberately null columns (reporting_classifiers.json:203). G8-w or the engine path must supply them before activation.
  • Veteran's Pension receipt and amount are unsupported. A missing flag refuses rather than implying false. G8-w supplies them and extends the AS non-beneficiary closure.
  • A1 stays provisional:
    • its gross-income basis waits on D2 (addendum A1);
    • the weighted midpoint is a disclosed provisional detail (:190);
    • rental and private-pension donor concepts lack explicit tax wording, so they are flagged for activation review.

Invariants (Hypothesis and example tests)

  • Income cells are invariant to row permutation, and to any exact common scaling of the weights, for example by a power of two. Scaling by a non-dyadic factor such as 0.1 changes the stored floats themselves (0.3 × 0.1 = 0.30000000000000004), so cells may change; the method doc says so.
  • Ties split by stable unit id.
  • Zero, single and equal-weight units are handled.
  • Clones stay distinct reporting units, so equal-income, equal-weight clones can land in different cells; ties split by stable id.
  • Baseline labels survive variant changes to income, receipt and weight (test_transport_reporting_kernels.py:267).
  • The native graph covers all nine scenarios and all 43 cells (:485).

Tests

Hub re-run at this head, one file per run:

File Result
test_reporting.py (new, frame) 90 passed
test_transport_reporting_kernels.py (new) 31 passed
test_nz_spec_package.py 88 passed
test_country_spec.py 135 passed
test_spec_only_country_packages.py 8 passed
test_transport_graph.py 15 passed
test_transport_entitlement_graph.py 46 passed

ruff check, tools/ci_test_plan.py verify and git diff --check pass.

Mutants (each failing a named test, with a passing control):

  • unweighted ranks → test_exact_weighted_midpoint_boundaries_and_uneven_weights;
  • row-order ties → test_boundary_ties_split_by_stable_unit_id;
  • beneficiary-first priority;
  • net instead of before-tax payment;
  • including housing payments;
  • recomputing in the variant instead of carrying the baseline.

Mutant logs are in the lane report.

The NZ golden country spec is regenerated (bced1c2). Only the as_rate_bridge, gates and country_package hashes move, the new reporting_classifiers resource is added, and the fingerprint changes; each hash equals its committed file.

How it was built

  • A GPT-6.1 Sol lane wrote it (a6a1deb). The 11:42Z reboot interrupted it; it resumed and finished its own tests and mutants.
  • Its three required regressions (transport graph, NZ spec, entitlement graph) stalled on file reads in the lane, so the hub ran them, with the results above.
  • Provenance now points into the repository: docs/nz-reporting-classifiers-method.md holds the A1/A2 method basis and the SSR 2018 reg 17/18 reading, and each provenance entry in reporting_classifiers.json anchors to it.

Review

  • r1, 20261012-201438 (GPT-6.1 Sol) at bced1c2: REQUEST_CHANGES.
    • P1: the weighted-midpoint deciles broke the exact-boundary and weight-scaling invariants. Cumulative float rounding exceeded a fixed eps × n_bins × 4 snap.
    • Its counterexample: 625 units, left = tile([78, 46, 37], 104), weights = [left, 80, left]. Unit 312's exact midpoint is ½, so cell 6, but scaling every weight by 0.1 moved it to cell 5. It also found 14 boundary and 2 scaling failures in larger symmetric populations.
    • Non-blocking: the false "clones share cells" claim, and provenance that cited a source outside the checkout.
    • Its "Needs Max" (publishing reporting-method claims) was judged no: the NZ package is inactive and publishes no number.
  • Fix, d3827c0 (GPT-6.1 Sol lane):
    • exact dyadic-integer midpoint ranks;
    • regressions for the reviewer's 625-unit case (exact and under 0.1 scaling) and for larger symmetric populations;
    • property generators to large n, a power-of-two scaling property, and a fractions.Fraction oracle differential;
    • a mutant restoring the old float cumsum fails 10 tests;
    • 500,000 units take 0.70 s for the decile step alone (lane's measurement). The r2 reviewer measured the full classifier at 1.65 s / 4.21 s / 11.77 s for 100k / 300k / 500k units, with sorting O(N log N) and the rest linear;
    • the clone wording and the in-repo method doc.
  • The hub then recorded the lane's merge of main (c62a2c2) as merge commit d3827c0, merged current main (Settle and apply the NZ dependent-child benefit-unit rule (G8-u) #1226) and regenerated the golden (41d20a3). Relative to main, only the four G8-p resource hashes and the fingerprint differ.
  • Re-run at 41d20a3: test_reporting 111, transport_reporting 31, nz_spec 89, country_spec 135, spec_only 8, entitlement_graph 67. ruff check, the CI plan and diff-check pass.
  • r2, 20261013-000212 (GPT-6.1 Sol) at 41d20a3: APPROVE_WITH_NITS.
    • The ten-bin computation is exact for finite non-negative float64 weights, subnormals and mixed extremes included: 254 independent probes, including the 625-unit case at scales 1 and 0.1.
    • The Fraction oracle is independent. The old-accumulator mutant gives 10 failures. 159 new test instances each go red under mutation.
    • The resource hashes, fingerprint, 105 provenance entries and 117 citation anchors all verify.
    • Its entitlement run was interrupted at the disk floor after 46 passed. The hub's run at 41d20a3 had 67 passed.
  • Its nits are applied in 70f1706:
    • the A2 method note now cites the pinned SSR 2018 PCO XML (axiom-corpus release nz-rulespec-2026-07-25, path and sha256 5f1250b9…);
    • the MC11 predicate citation in as_rate_bridge.json points to the in-repo note instead of a local path;
    • the tie-key evidence names build_benefit_units instead of stale line numbers;
    • the golden is regenerated;
    • the scaling invariant above is scoped and the benchmark explained.
  • Tests at 70f1706: nz_spec 89, country_spec 135, reporting 111; diff-check ok.
  • After r2:
  • r3 delta, 20261013-114729 (GPT-6.1 Sol) at e4753f7: APPROVE_WITH_NITS.
    • Executable declarations and classifier/transport bytes match r2. country_package.json is the exact union of both merge parents. The golden recomputes byte-equal (4,645 bytes), with all 24 resource hashes current.
    • 388 tests pass across the five delta files. Both delta mutants fail (dropping the resource from the expected set; altering a golden hash), with controls passing before and after.
    • ruff check, the CI plan and diff-check pass.
    • Its one nit (P3): the pinned SSR XML isn't in this checkout, so it could not reproduce the hash.
  • The hub closed that nit from axiom-corpus origin/main (9a17ccac):
    • .axiom/corpus-locks/nz/regulation/2026-06-16-rulespec-nz-pco.json records the cited path with sha256 5f1250b9…85d8f and size 1,272,548. The local corpus file hashes to the same value.
    • Release manifest manifests/releases/nz-rulespec-2026-07-25.json includes that regulation scope.
    • The hub read regulations 17 and 18 in that XML. Both match the method note:
      • regulation 17(1) defines beneficiary and non-beneficiary as the note says;
      • regulation 18(1)(b) and (2) apply the 25-cents-per-dollar reduction only to a non-beneficiary.
  • An earlier r3 attempt on an Opus lane hit its usage limit before delivering; its notes were passed to this review as unverified claims.
  • The earlier lane and restart history above is the hub's and lanes' report, not re-verified by the reviewers.
  • All three reviews' "Needs Max" flags (publishing reporting-method and regs 17/18 prose) were judged no by the hub:
    • the NZ package is inactive and publishes no number;
    • the note restates the regulation text, which the hub checked against the pinned source;
    • the note itself labels the three-way split a reporting convention, not law.

🤖 Generated with Claude Code

MaxGhenis and others added 2 commits October 12, 2026 11:06
Implement weighted income cells, strict assigned receipt groups, and typed
baseline mappings carried into scenario branches by stable unit ID. Declare
NZ A1/A2 parameters, shared MC11 predicate and expected structural zeros;
keep unresolved gross payment and Veterans Pension inputs fail-closed.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The as_rate_bridge, gates and country_package resource hashes move, the
new reporting_classifiers resource is added, and the fingerprint changes;
each hash equals sha256 of the committed file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 3 commits October 12, 2026 23:55
…ance

Merge origin/main while preserving reporting admissions and cell-contract
validation. Use exact dyadic integer midpoint ranks, cover large populations
against a Fraction oracle, and document distinct clone reporting units.
Archive A1/A2 methods with local provenance anchors and regenerate the NZ golden.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	packages/microcosm-build/tests/golden/nz_country_spec.json
The A2 method note now cites the pinned axiom-corpus release, path and
sha256 of the SSR 2018 PCO XML it was read from. The MC11 predicate
citation in as_rate_bridge.json points to the in-repo method note instead
of a local absolute path, and the tie-key evidence names
build_benefit_units rather than stale line numbers. NZ golden regenerated
for the two resource hashes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis marked this pull request as ready for review October 13, 2026 08:04
MaxGhenis and others added 2 commits October 13, 2026 04:41
…w test

The expected legacy_json set in test_nz_generation_zero_views_come_from_
the_country_spec_seam predates the new nz/reporting_classifiers.json
resource (the same gap CI found for #1249's chronicle_feed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The golden now pins both chronicle_feed.json (from #1249) and
reporting_classifiers.json (this PR); every other resource hash equals
one side of the merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis merged commit 4b33e3c into main Oct 13, 2026
10 checks passed
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Merged by the NZ hub (session local_e407a527) at e4753f7 with --squash. Gates: gh pr checks exit 0; MERGEABLE; not draft; no CHANGES_REQUESTED review. Reviewed head: e4753f7. Reviews (GPT-6.1 Sol): r1 REQUEST_CHANGES at bced1c2 (fixed), r2 APPROVE_WITH_NITS at 41d20a3, r3 delta APPROVE_WITH_NITS at e4753f7 (jobs/review-microcosm-1234/REPORT-114729.md). r3 P3 nit closed: SSR XML sha256 verified against axiom-corpus lock file at origin/main 9a17ccac. Needs Max judged no: inactive NZ package, no published number; regs 17/18 reading checked against the pinned text.

@MaxGhenis
MaxGhenis deleted the nzhub/g8p-classifiers branch October 13, 2026 16:38
juaristi22 added a commit that referenced this pull request Oct 17, 2026
The drafter's free-text rule (1307-02) treated any #N or word#N as an
issue reference, so it accepted text that numbers a record or a cell:
"household #4521 carries weight #312", "record #1234 decides the cell",
"#7 rows against the #50-row floor". It took any four-two-two digit
group for a date ("household 1234-05-06"), and its percent check missed
the full-width sign ("#25" followed by U+FF05). Meanwhile it refused the
repository's usual citations: issue-comment anchors and full GitHub
URLs. The --approved-by check accepted login-shaped figures such as
"4521" and "rows-7-of-50".

figure_free now strips only the citations it can tell from a figure:
microcosm#N, chronicle#N, uk-data#N and PolicyEngine/<repo>#N, each
optionally anchored #issuecomment-N, with nothing running into the
reference from the left; GitHub URLs of a PolicyEngine issue or pull
request, optionally anchored the same way; and ISO dates of real days
in 2000-2099. Any digit left, a bare #N included, refuses the text, as
does a percent sign in any form NFKC folds into "%" and the Arabic,
per-mille and per-ten-thousand signs. A comment cited as "issue comment
N" stays refused; its anchor form passes. --approved-by must also start
with a letter and hold at most one run of digits, within GitHub's login
shape, so ordinary logins such as juaristi22 pass.

The review's probes and the accepted citation forms are parametrized
tests, beside numbers that stay refused because the rule cannot tell
them from a figure (K=15, a plan code, a bare year).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant