Repository navigation
Conversation
The generator adds the TY2026 wage interval table ird_wage_salary_national_ty2026 (rows 7-241, right-closed, no nil band, negative wages refused, open tail over $1,000,000) from the pinned feed's labels, and activates the 235 P1 precal rows, which drops their exemptions. The transport builder writes earnings_bands.json: for each aging_index profile, every edge is cut_cents x P1 factor / 100, computed in Fraction and rounded once to binary64, with the factor id, its receipt SHA-256 and the wage table's SHA-256. nz.earnings.map (transport.quantile_map@2, grouped_pareto_mle@1 on rows 231-241) rewrites person.employment_income beside nz.money.normalize, and nz.earnings.cents writes employment_income_cents half-even, both before nz.encode.person. Each calibration variant repeats them with its own profile (V1 low, V2 high). R2C-6 adds person.employment_income to the export contract and both slices. Three wage labels repeat the previous upper endpoint ($20,000, $50,000, $80,000: rows 27, 57, 87); the generator pins them and the right-closed cuts give each endpoint to the lower band. Invariants: every edge equals cut x factor exactly for every profile (example test, plus a builder --check that refuses a hand-edited edge, a stale factor receipt, a stale table and a changed tail); the edges stay contiguous and increasing for any positive factor (Hypothesis); the scaled-edge map equals the unscaled map x f within 2^-49 relative (measured at most 4.3e-16); the toy's @2 support row is quantile_mapped with 0 records outside. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6Fwj4yUEPsD3wfNstU
test_nz_spec_package pins the active row count per reference set. G8-r2c E activates the 235 wage rows, so precal's active count moves from 80 to 315. The calibration and hold-out counts stay as they were. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6Fwj4yUEPsD3wfNstU
This was referenced Nov 2, 2026
The hub's R2C-19 lifts the freeze for these tests on E. Each edit follows from what E changes in NZ's own resources: - test_spec_engine_country_bundles: NZ's legacy resources include earnings_bands.json. - test_transport_composed_graph: _GAPS no longer names the person.employment_income quantile-map gap, which nz.earnings.map closes. - test_transport_evidence_kernels: the roster gains one quantile_mapped row (R2C-6), and derived rows miss only rent and liquid assets; the per-row assertion over every derived row stays. - test_transport_quantile_map_v2: _spec_with_map first removes the packaged nz.central producer of employment_income, so the kernel under test stands alone; that spec without a map still reports a central wage gap; the packaged spec reports none. Both accepted kernels and the transport.currency@1 refusal stay. Mutant run: with _money_producer_gaps accepting any kernel, test_composition_accepts_v2_as_the_quantile_mapped_money_producer goes red (the currency@1 refusal finds no gap). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6Fwj4yUEPsD3wfNstU
This was referenced Nov 3, 2026
Merged
Contributor
Author
|
Closing as included: #1478 landed this PR's commits on main in merge commit 🤖 Generated with Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
G8-r2c hunk E (#1183): NZ maps P1 wages onto IRD's wage bands with
transport.quantile_map@2. Draft. Basenzhub/g8r2c-int; F (#1476) and G (#1478) stack on it.N/ispackages/microcosm-build/src/microcosm/build/nz/,T/isB/transport/, tests are inpackages/microcosm-build/tests/engine_free/shared/, and file:line is at G's head (64ef20af) unless a line says otherwise.Landing (R2C-21a, #1183 comment 6604753490). E lands with F and G in #1478's one merge commit, and the hub then closes this PR as included. E's head has two merge bases with main (D's head
91bf4c0fand C's fix-round headacfa6b94, which main took in through their own PRs), so GitHub marks this PR as conflicting against main, though git's own merge changes exactly E's 28 files. The fix branch's top,f43e8fbb(#1486), merges main4a36edcfand has one merge base with main, so #1478 lands the whole stack and main's history keeps every commit of E, F and G.Change
ird_wage_salary_national_ty2026inN/reference_intervals.json, generated bytools/generate_nz_target_references.py:1181(wage_interval_table) from the pinned feed's labels: person,employment_income_cents, right-closed,nil_band: absent,negative_income_policy: refuse,first_lower_cut_cents: 0, 235 bands (rows 7-241) ending in the open tail over $1,000,000. Declared and validated only, with no companions.WAGE_SHARED_ENDPOINT_ROWS,:150) and refuses any change, and the right-closed cuts give each endpoint to the lower band, as the taxable table does. Row 240 spells its upper "$1 million".active(:736addsquantile_producerand the table id), so_reference_selectiondrops their exemptions.N/earnings_bands.json, written bytools/build_nz_transport_graph.py:304(earnings_bands_document). For eachaging_indexprofile, every edge isfloat(Fraction(cut_cents) × P1 factor / 100)(scaled_edge,:299), with the factor id, its operational factor, its receipt SHA-256 and the wage table's SHA-256. Each profile carries the bare band list@2reads (map_bands, keys{"bands"}only).N/reference_aging.json,p1_ty2026_to_ty2027_*).--checkrunsvalidate_earnings_bands(:384), which recomputes every edge and refuses a stale edge, factor receipt, table digest or tail by name.earnings_nodes,:413):nz.earnings.map(transport.quantile_map@2) rewritesperson.employment_incomeonnz.centralbesidenz.money.normalize, reading the precal surface;nz.earnings.cents(money.minor_units@1, half-even) writesemployment_income_cents. Both precedenz.encode.person.earnings_bands.jsontails.centralanchorsgrouped_pareto_mle@1on rows 231-241 (row 231 is "$500,001 - $550,000");tails.vpton rows 227-241 (row 227 is "$300,001 - $350,000"). Bracket["1.00000095367431640625", "64"], 64 iterations. No two-point closed form.@2rewrite output (:1139-1154), soperson.employment_incomeis inoptionaland bothentity_slicesofN/export_contract.json.tools/build_nz_entitlement_graph.py:626passes each calibration variant'saging_index(V1 low, V2 high) to its own map node.pending_outputsdrops P1 earnings;N/money_normalization.json'semployment_incomeentry names the producer.Shared code read at int
_surface_bands(T/population_kernels.py:411-455) reads onlylower,upperandreferencefrom the params and never compares an edge with the reference's own bounds.@2'sestimated_alpha(T/quantile_kernels.py:54-112) calls it, then requires the anchors to be the band list's top suffix. So the scaled TY2027 edges pair with the TY2026 rows without a shared-code change.grouped_pareto_mlereads edges as exact binary64 fractions (B/tail_estimators.py,_edge), and α is scale-invariant.Invariants and tests
test_nz_transport_declarations.py::test_every_profiles_edges_equal_cut_times_factor_exactlytest_the_builder_check_refuses_each_stale_earnings_declaration(4 cases)test_the_wage_map_and_cents_precede_the_person_encoder_on_every_branchnz.earnings.maptest_r2c6_exports_employment_income_on_the_export_and_both_slicestest_nz_reference_intervals.py::test_resolution_is_not_activation_and_no_active_row_requests_the_proxy,test_nz_target_references.pyreceipt testtest_nz_target_references.py::test_wage_cuts_match_the_feed_labels_and_the_committed_tabletest_nz_earnings_bands.py::test_property_edges_stay_contiguous_and_increasing_for_any_positive_factor(Hypothesis, 60 examples)test_nz_earnings_bands.py::test_scaled_edge_map_equals_unscaled_map_times_the_factor@2support row isquantile_mapped, 0 outside, both bounds open; α = 2 on scaled toy edgestest_nz_transport_toy_graph.py::test_the_wage_map_v2_support_row_is_quantile_mapped_with_none_outside,test_the_wage_map_v2_fits_the_toy_alpha_on_scaled_edges@1Differential tolerance. 2^-49 relative (about 1.8e-15). The scaled path rounds each edge once and then interpolates; the unscaled path interpolates and multiplies by f once more. The uniform branch takes three roundings and the Pareto branch two, so the paths differ by a few half-ulps. Measured on 4,000 lognormal values with α = 2.4: at most 4.30e-16 (low), 3.90e-16 (central), 2.95e-16 (high), matching design 80's 3.9e-16.
R2C-19 shared-test edits (commit
385d5967)Line ranges at this head, for Belgium's hub:
test_spec_engine_country_bundles.py:246(G moves this line to its sorted place under R2C-23)test_transport_composed_graph.py:2755(_GAPSdrops the wage gap)test_transport_evidence_kernels.py:2710and:2715(onequantile_mappedrow;pendingdropsperson.employment_income; all 307 derived rows miss exactly rent and liquid assets, so no other count moves)test_transport_quantile_map_v2.py:673-696(_spec_without_central_wage_producer,_spec_with_map) and:729-732(the packaged spec has no central gap; without its producer it has one)R2C-19's mutant:
_money_producer_gapsaccepting any kernel turnstest_composition_accepts_v2_as_the_quantile_mapped_money_producerred at thetransport.currency@1refusal.Hashes
The hub hashed 42 engine-free transport kernels (no
simulate.*) at each head, each in its own tree: int3e5f5edb, E8ec98c1c, F623afa09and Ga3fe1952, after which G's head64ef20afchanges only two test files. E, F and G hash identically to int, as does the int before D's merge (ba08d0f9), so this hunk moves no kernel hash.909fe3cb3e5f5edb(=ba08d0f9, E, F, G)calibrate.ordered_adam@10d4577effa147ebe0d4577effa147ebecalibration.prepare@1180823901b9a0d99180823901b9a0d99concepts.encode@17815fae8ed573af67815fae8ed573af6concepts.encode_groups@1062f88411ad605ab062f88411ad605abdiagnostics.calibration@130654dfc7038f56030654dfc7038f560export.prepare@1af31fa6e1690b90caf31fa6e1690b90cexport.readback@196be393c760ca76896be393c760ca768gates.battery@1ac050bab09f48dc2ac050bab09f48dc2geography.assign_atomic@1d60f7ec388903678d60f7ec388903678geography.derive@1d60f7ec388903678d60f7ec388903678geography.gate@1d60f7ec388903678d60f7ec388903678geography.person_location@13efcbe3741d044973efcbe3741d04497geography.support_from_facts@1ad0a8e73d20405bead0a8e73d20405begeography.support_import@1d60f7ec388903678d60f7ec388903678measure.combine@1d609832882ffc113d609832882ffc113money.annual_transfers@1c8a067cd750ed2fec8a067cd750ed2femoney.minor_units@1c8a067cd750ed2fec8a067cd750ed2femoney.normalize@1f10fbeeaf87467b6f10fbeeaf87467b6reporting.carry_income_decile@180335f0183c2741080335f0183c27410reporting.income_decile@180335f0183c2741080335f0183c27410reporting.receipt_group@180335f0183c2741080335f0183c27410takeup.assign@1b2a3a50cc376108bb2a3a50cc376108btakeup.bands@11ceca3ba7c7c9b921ceca3ba7c7c9b92takeup.cell_diagnostics@11ceca3ba7c7c9b921ceca3ba7c7c9b92takeup.compare@11605d7e8519f4b0f1605d7e8519f4b0ftakeup.gap@154f79560d896fab454f79560d896fab4targets.compile@1dc91d1479f8f84b1dc91d1479f8f84b1targets.problem@1fe401c736551e351fe401c736551e351transport.boundary@1fc9d10670f6a092ffc9d10670f6a092ftransport.create@1865c21926cee0ac0865c21926cee0ac0transport.create@2865c21926cee0ac0865c21926cee0ac0transport.currency@19c3457ddb908aa969c3457ddb908aa96transport.donor_ranges@162def362139a52e462def362139a52e4transport.donor_receipt@162def362139a52e462def362139a52e4transport.input_closure@123134112061495b723134112061495b7transport.package@1e86be552287a6eb3e86be552287a6eb3transport.quantile_map@1b25bb6538b19dd64b25bb6538b19dd64transport.quantile_map@2b845aac2c57f667b76c81605aa416dc9(moved)transport.scenario_override@1062f88411ad605ab062f88411ad605abtransport.support_bounds@12303c60a7ec6135c2303c60a7ec6135ctransport.unit_attributes@1f50ec74a1bfe35bbf50ec74a1bfe35bbtransport.weights_audit@11f3d4750134561271f3d475013456127transport.quantile_map@2moves only through int's merge of B'stail_estimators.pydocstring fix, which it digests.Tests
Closed list at int
ba08d0f9, E3e850e07and Ff5ed82ba(G at #1478), no--maxfail,-n 2. Counts read passed / skipped / failed. Merges of D's head (91bf4c0f) moved int to3e5f5edb, E to8ec98c1cand F to623afa09, and against each earlier head they change onlyT/compose.py,test_transport_measurement_prefit.pyandtest_transport_measurement_proof.py. The hub reran those two files at each new head (-n 0, with the feed):3e5f5edb8ec98c1c623afa09test_transport_measurement_prefit.pytest_transport_measurement_proof.pyThe E-G review ran F's list at
623afa09and found the same one red. F never lands alone, so its one red test never reaches main: G passes it, and E, F and G land together in #1478's merge (R2C-21a).The closed list at the earlier heads:
frame/test_transport_donor.pyframe/test_transport_quantile.pytest_country_spec.pytest_nz_as_area_crosswalk.pytest_nz_as_bridge.pytest_nz_axiom_input_closure.pytest_nz_benefit_gross_up.pytest_nz_earnings_bands.pytest_nz_family_reconciliation.pytest_nz_joint_geography.pytest_nz_money_normalization.pytest_nz_msd_benefit_rates.pytest_nz_msd_pre_activation_reconciliation.pytest_nz_reference_aging.pytest_nz_reference_intervals.pytest_nz_spec_package.pytest_nz_target_references.pytest_nz_transport_declarations.pytest_nz_transport_toy_graph.pytest_reference_interval_support.pytest_reference_intervals.pytest_reference_profiles.pytest_reference_summed_bands.pytest_spec_engine_country_bundles.pytest_spec_only_country_packages.pytest_transport_annual_transfers.pytest_transport_binding_identity.pytest_transport_bridge_differential.pytest_transport_codecs_geography.pytest_transport_column_kernels.pytest_transport_composed_graph.pytest_transport_declared_units.pytest_transport_dependent_children.pytest_transport_entitlement_graph.pytest_transport_evidence_kernels.pytest_transport_gate_bindings.pytest_transport_gate_kernels.pytest_transport_graph.pytest_transport_grossup_selectors.pytest_transport_measure_kernels.pytest_transport_measurement_prefit.pytest_transport_measurement_proof.pytest_transport_money_kernels.pytest_transport_population_kernels.pytest_transport_quantile_map_v2.pytest_transport_receipt_v2.pytest_transport_receipt_v2_kernel.pytest_transport_reference_selection.pytest_transport_registry.pytest_transport_reporting_kernels.pytest_transport_run_entry_factors.pytest_transport_run_entry_forms.pytest_transport_source_household_lineage.pytest_transport_takeup_kernels.pytest_transport_target_kernels.pytest_transport_terminal_kernels.pytest_transport_weight_quality.pyuk/test_transport_gate_bindings.pySkips (18 at each head), each needing a source this container lacks:
test_nz_joint_geography.py11 (NZ_AS_AREA_SOURCES and NZ_JOINT_GEOGRAPHY_SOURCES unset);test_nz_as_area_crosswalk.py3 (pinned ArcGIS bytes);test_nz_axiom_input_closure.py2 (Axiom dense engine and a rulespec-nz checkout);frame/test_transport_donor.py2 (pinned real donor not cached). EveryNZ_CHRONICLE_ARTIFACTfeed audit ran, against the artifact I built from Chronicle8f4cfd57(both digests match the pin).Also at each head:
ci_test_plan.py verifyprintsverification=ok; the three source-free NZ builders'--checkandgenerate_nz_target_references.py --check(with the artifact) match; ruff is clean on the changed files.Generated by Claude Code