diff --git a/changelog.d/nz-reference-ageing-factors.added.md b/changelog.d/nz-reference-ageing-factors.added.md new file mode 100644 index 0000000000..2f8a2967d2 --- /dev/null +++ b/changelog.d/nz-reference-ageing-factors.added.md @@ -0,0 +1,15 @@ +Add declaration-driven, exact feed-derived reference ageing factors with certified +root bounds, once-only rounding, selected evidence identities and authenticated +compiler replay. Declare the reviewed NZ ageing profiles and their explicit money +and count companions while keeping the income references parked for measurement +closure. + +Retain authenticated decimal tokens only with explicit lexical-float loading for +selected factors; ordinary loads keep plain floats and their serializer and memory +behavior. Bind factor application to the selected money/count roster and preserve +count operations. Certify exact-root ties in the independent oracle and bound +supported schedules so exact receipts remain serializable. Float selector pins +match token-retaining floats while keeping booleans, integers and floats distinct. +Scan extra feed-identity fields for RuleSpec commits. Bind factor evidence to +reviewed feed identities while allowing prose-only pin edits; refuse replay when +the source commit cannot be authenticated. diff --git a/changelog.d/nz-reference-intervals.added.md b/changelog.d/nz-reference-intervals.added.md new file mode 100644 index 0000000000..34cd83efed --- /dev/null +++ b/changelog.d/nz-reference-intervals.added.md @@ -0,0 +1,24 @@ +Add exact income-band intervals: a shared, declaration-driven interval module +with no default semantics (closure, nil band, negative-income policy, first lower +cut, entity, columns and diagnostics window are all declared per table), +integer-cent source cuts, exact rational scaling that never rounds an aged cut, +universe-aware classification that refuses unresolved records or invalid amounts +before any indicator exists, and fixed-weight boundary diagnostics weighted +through `resolve_weights(entity)`. + +`scale_money_and_intervals` now scales named interval tables with the same +selected factor as their money companions and binds each scaled table to its +source and factor. Interval outputs are their own calibration binding kind. +Preparation passes the effective interval document into column preparation and +records its digest, payload and input fingerprints; the problem kernel binds a +boundary diagnostics report without changing any target. Composition supplies +each variant its own effective interval companion. Declare the NZ national +(237 bands) and age (183 bands) taxable-income tables under Microcosm's declared +convention; the 474 IRD references stay parked. + +Require the first cut explicitly. When a nil band is present, zero is nil under +either closure, so with a zero first cut the first positive band starts above +zero. Report below-first-cut mass and floored negative records, including +weighted counts and signed pre-floor amounts by destination. These diagnostics +describe fixed weights before fitting; reporting later weight changes on +unfitted records remains G8-r2c/G8-x work. diff --git a/docs/nz-calibration-targets.md b/docs/nz-calibration-targets.md index 2cc12cf60f..89df2cb487 100644 --- a/docs/nz-calibration-targets.md +++ b/docs/nz-calibration-targets.md @@ -99,6 +99,46 @@ All statistical spreadsheets on the un-gated `ird.govt.nz` CDN (HTTP 200 confirm Notes: **I1, I3, I4 are the load-bearing IRD targets.** IRD income tables are **individual-level** — joint/couple income unpublished. **FamilyBoost: no public statistics dataset confirmed** — only a modelled `Value_Type` in Treasury DistributionExplorer [UNCONFIRMED — re-check]. +### I1 taxable-income bands: a declared convention (G8-r2b, 2026-10-24) + +IRD publishes no band closure or cents semantics for the I1 tables. The +workbook introduces an "income between $0.01 and $100" band, and four label +pairs share an endpoint ($20,000, $50,000, $80,000 and $300,000: national rows +29/30, 59/60, 89/90 and 229/230; age rows 27/28, 57/58 and 87/88). Microcosm +therefore applies its own declared convention, not IRD's semantics (G8-r open +rulings 2, section 1): + +- t = max(0, x) in integer cents, with no dollar rounding; +- t == 0 is the nil band, including qualifying loss records; +- each positive band is `previous_upper < t <= upper`, and the open tail is + `t > its lower cut` (national top band over $1,000,000, age table over + $180,000); +- the ordered right-closed cuts give each shared endpoint to the lower band. + +`build/nz/reference_intervals.json` holds the two tables: the national table +(237 bands, rows 8–244, each naming its parked count and amount references) +and the age table (183 bands, rows 6–188, no references and no fit rows). +`tools/generate_nz_target_references.py` generates both from the row formulas +and checks every cut against the pinned feed's own band labels. Ageing scales +the national cuts exactly by the selected factor and keeps fractional cents: +under the central factor 1.117109, $100 becomes 11,171.09 cents and $1,000 +becomes 111,710.9 cents. Before matrix construction the calibration problem +reports, for every cut, the weighted mass within $1, and for every band the +fixed-weight change under the left-closed alternative. These diagnostics never +change a target, and publisher reclassification is unavailable, because the +published histogram does not identify mass exactly on a cut. + +The shared diagnostics also report records below a table's first lower cut, +including their weighted count and amount. Floored negative records retain +their separate count and signed pre-floor amount, grouped by destination. +These are fixed-weight, pre-fit measurements; reporting the later weight +changes on these unfitted records remains G8-r2c/G8-x work. + +The income and universe columns (`ird_taxable_income_proxy_cents`, +`ird_taxable_income_proxy_universe_status`) name the d1952 stand-in measure +rather than IRD's definition. No producer exists yet (G8-r2c), no active row +requests them, and all 474 IRD rows stay parked. + ## 3. MSD **Critical structural finding:** the **quarterly Benefit Fact Sheets are COUNT-ONLY** (every sheet opened; only hardship reports dollars). **Dollar-level data comes from the Annual Report** expenditure schedule (explicit CC BY 4.0). diff --git a/docs/nz-take-up-engine-plan.md b/docs/nz-take-up-engine-plan.md index 1569e61cf8..2e765dffff 100644 --- a/docs/nz-take-up-engine-plan.md +++ b/docs/nz-take-up-engine-plan.md @@ -129,9 +129,12 @@ tenure targets close to each region's published Census household total before the existing ERP bridge. Calibration variant V4 concentrates only the size residual onto one- and two-person households. The implementation preserves raw discrepancies and independent national diagnostics, and supplies validated size -columns before activation. G8-r2 reuses the same resolver for ageing profiles -and interval preparation; central ageing remains explicitly deferred and V1/V2 -ageing transformations remain unavailable until that work lands. +columns before activation. G8-r2 reuses the same resolver for ageing: each +low, central or high profile scales the IRD money references and, exactly, the +national taxable-income band cuts by its own feed-derived factor, and the +interval tables declare Microcosm's band convention (see +[the target inventory](nz-calibration-targets.md)). The 474 IRD references +stay parked until the B4 stand-in measure's producer lands (G8-r2c). - **Pre-calibration:** IRD wage and salary bands, MBIE bond rents by TA, Stats NZ household financial net worth, TA population, and the same MSD recipient facts as the calibration set (the take-up draws calibrate to them). diff --git a/packages/microcosm-build/src/microcosm/build/calibration_columns.py b/packages/microcosm-build/src/microcosm/build/calibration_columns.py index be3897d360..c7a986b21b 100644 --- a/packages/microcosm-build/src/microcosm/build/calibration_columns.py +++ b/packages/microcosm-build/src/microcosm/build/calibration_columns.py @@ -1,7 +1,8 @@ """Prepare simple calibration columns from an explicit, engine-free contract. Geography and canonical concepts must already be present. This helper creates -constants, validated roster counts and conjunctions of declared predicates; +constants, validated roster counts, conjunctions of declared predicates and +interval indicators classified by :mod:`microcosm.build.reference_intervals`; receipt assignment and statistical-unit construction belong to their own producers. """ @@ -15,15 +16,26 @@ import numpy as np import pandas as pd +from microcosm.build.reference_intervals import ( + interval_indicators, + validate_interval_document, +) + def prepare_calibration_columns( - tables: Mapping[str, pd.DataFrame], bindings: Mapping[str, Any] + tables: Mapping[str, pd.DataFrame], + bindings: Mapping[str, Any], + *, + intervals: Mapping[str, Any] | None = None, ) -> dict[str, pd.DataFrame]: """Return independent tables with the contract's prepared columns. All required inputs are validated before any column is produced. Existing prepared columns are recomputed, so a changed geography or age cannot retain stale indicators. Missing/unknown inputs never become all-false categories. + An interval output names its entity, an effective table of ``intervals`` + and one of its bands; every record of each named table is validated, and + any refusal raises, before an output exists. """ if bindings.get("schema_version") != 1: raise ValueError("Calibration bindings require schema_version 1.") @@ -48,6 +60,7 @@ def prepare_calibration_columns( raise ValueError(f"Calibration input {entity}.{name} needs a domain.") _validate_input(tables[entity][name], domain, f"{entity}.{name}") + interval_columns = _interval_columns(tables, columns, required, intervals) out = {entity: table.copy(deep=True) for entity, table in tables.items()} derived = _prepare_roster_counts(out, bindings.get("roster_counts", ()), required) prepared: dict[str, dict[str, object]] = {} @@ -69,6 +82,9 @@ def prepare_calibration_columns( f"Calibration output {entity}.{name} is repeated or structural." ) seen.add(key) + if "interval" in entry: + prepared.setdefault(entity, {})[name] = interval_columns[key] + continue if "constant" in entry: value = entry["constant"] if "predicates" in entry or not _finite_number(value): @@ -115,6 +131,81 @@ def prepare_calibration_columns( return out +def _interval_columns( + tables: Mapping[str, pd.DataFrame], + columns: object, + required: Mapping[str, Any], + intervals: Mapping[str, Any] | None, +) -> dict[tuple[str, str], np.ndarray]: + """Classify every named table once; refuse before any output is produced.""" + entries = [ + entry for entry in columns if isinstance(entry, Mapping) and "interval" in entry + ] + if not entries: + return {} + if intervals is None: + raise ValueError("Interval outputs need the effective interval document.") + document = validate_interval_document(intervals) + requested: dict[str, list[tuple[str, str, str]]] = {} + for entry in entries: + entity, name, binding = ( + entry.get("entity"), + entry.get("name"), + entry["interval"], + ) + if set(entry) != {"entity", "name", "interval"}: + raise ValueError( + f"Interval output {entity}.{name} declares only its entity, name " + "and interval." + ) + if not isinstance(binding, Mapping) or set(binding) != {"table", "band"}: + raise ValueError("An interval output names exactly its table and band.") + table = document.get(binding["table"]) + if table is None or binding["band"] not in table.band_ids: + raise ValueError( + f"Interval output {entity}.{name} names an undeclared table or band." + ) + if entity not in required or entity != table.entity: + raise ValueError( + f"Interval output {entity}.{name} must name its table's entity." + ) + if name != table.indicators[table.band_ids.index(binding["band"])]: + raise ValueError( + f"Interval output {entity}.{name} must be its band's declared indicator." + ) + if ( + table.declaration["source_period"] != table.declaration["target_period"] + and not table.scaled + ): + raise ValueError( + f"Interval table {table.id!r} has source-period cuts; scale it to its " + "target period before preparing indicators." + ) + requested.setdefault(table.id, []).append((entity, name, binding["band"])) + result: dict[tuple[str, str], np.ndarray] = {} + computed = {} + for table_id in requested: + table = document[table_id] + data = tables.get(table.entity) + if data is None or any( + column not in data + for column in (table.income_column, table.universe_column) + ): + raise ValueError( + f"Interval table {table_id!r} needs {table.entity}." + f"{table.income_column} and {table.entity}.{table.universe_column}." + ) + computed[table_id] = interval_indicators( + table, + data[table.income_column].tolist(), + data[table.universe_column].tolist(), + ) + for table_id, outputs in requested.items(): + for entity, name, _ in outputs: + result[entity, name] = computed[table_id][name] + return result + + def _finite_number(value: object) -> bool: return ( isinstance(value, Real) and not isinstance(value, bool) and math.isfinite(value) @@ -196,6 +287,11 @@ def _validate_input(values: pd.Series, domain: Mapping[str, Any], name: str) -> for value in values.tolist(): _identity(value) valid = True + elif domain.get("kind") == "signed_integer": + valid = all( + isinstance(value, Integral) and not isinstance(value, (bool, np.bool_)) + for value in values.tolist() + ) elif domain.get("kind") == "nonnegative_integer": valid = all( _finite_number(value) and value >= 0 and value == int(value) diff --git a/packages/microcosm-build/src/microcosm/build/ledger_artifact.py b/packages/microcosm-build/src/microcosm/build/ledger_artifact.py index da0eb1968b..c181d68e9a 100644 --- a/packages/microcosm-build/src/microcosm/build/ledger_artifact.py +++ b/packages/microcosm-build/src/microcosm/build/ledger_artifact.py @@ -64,7 +64,9 @@ "CHRONICLE_FEED_RESOURCE", "ChronicleFeedPinMismatchError", "LedgerConsumerArtifact", + "LexicalFloat", "add_ledger_artifact_args", + "chronicle_feed_identity", "load_ledger_consumer_artifact", "resolve_ledger_artifact", "validate_chronicle_feed_pin", @@ -78,6 +80,51 @@ ALLOWED_LEDGER_ASSERTIONS = frozenset(("observation", "source_projection")) DEFAULT_LEDGER_ASSERTION = "observation" CHRONICLE_FEED_RESOURCE = "chronicle_feed.json" +_FEED_IDENTITY_FIELDS = ( + "source_commit", + "facts_sha256", + "manifest_sha256", + "artifact_schema_version", + "consumer_fact_schema_versions", + "consumer_fact_schema_sha256", + "fact_row_count", +) + + +def chronicle_feed_identity(feed_pin: Mapping[str, Any]) -> dict[str, Any]: + """Select reviewed source commit and loader-verified fields, excluding prose. + + The source commit is a caller declaration unless the authenticated manifest + also carries it; the artifact loader verifies the remaining six fields. + """ + missing = sorted(set(_FEED_IDENTITY_FIELDS) - feed_pin.keys()) + if missing: + raise ValueError( + f"Chronicle factor feed identity is missing fields: {missing}." + ) + if not isinstance(feed_pin["source_commit"], str) or not feed_pin["source_commit"]: + raise ValueError("Chronicle factor feed identity requires a source commit.") + return {field: feed_pin[field] for field in _FEED_IDENTITY_FIELDS} + + +class LexicalFloat(float): + """An opt-in float retaining its authenticated JSON numeric token. + + Request ``lexical_floats=True`` when loading operands for exact arithmetic. + The default loader returns plain floats, avoiding the instance and token + overhead and preserving compatibility with serializers requiring exact + float types. Standard JSON serialization retains the same numeric bytes. + """ + + __slots__ = ("lexical_token",) + + def __new__(cls, token: str): + instance = super().__new__(cls, token) + instance.lexical_token = token + return instance + + def __reduce__(self): + return type(self), (self.lexical_token,) class ChronicleFeedPinMismatchError(ValueError): @@ -250,6 +297,7 @@ def load_ledger_consumer_artifact( expected_facts_sha256: str | None = None, expected_manifest_sha256: str | None = None, feed_pin: Mapping[str, Any] | None = None, + lexical_floats: bool = False, ) -> LedgerConsumerArtifact: """Load a Ledger consumer artifact directory or bare consumer-facts file. @@ -259,6 +307,8 @@ def load_ledger_consumer_artifact( reviewed against; any mismatch raises before facts are used. ``feed_pin`` additionally checks all six reviewed artifact fields, without replacing the manifest integrity checks or either optional hash check. + ``lexical_floats=True`` retains numeric tokens for factor verification; + otherwise JSON decimals load as plain ``float`` instances. """ artifact_path = Path(path) if not artifact_path.exists(): @@ -314,7 +364,7 @@ def load_ledger_consumer_artifact( if feed_pin is not None: artifact = LedgerConsumerArtifact( path=artifact_path, - facts=_load_fact_rows(facts_path), + facts=_load_fact_rows(facts_path, lexical_floats=lexical_floats), facts_sha256=facts_sha256, manifest=manifest, manifest_sha256=manifest_sha256, @@ -340,7 +390,7 @@ def load_ledger_consumer_artifact( if artifact is None: artifact = LedgerConsumerArtifact( path=artifact_path, - facts=_load_fact_rows(facts_path), + facts=_load_fact_rows(facts_path, lexical_floats=lexical_floats), facts_sha256=facts_sha256, manifest=manifest, manifest_sha256=manifest_sha256, @@ -389,7 +439,9 @@ def resolve_ledger_artifact(args: Namespace) -> LedgerConsumerArtifact | None: ) -def _load_fact_rows(path: Path) -> tuple[dict[str, Any], ...]: +def _load_fact_rows( + path: Path, *, lexical_floats: bool = False +) -> tuple[dict[str, Any], ...]: rows: list[dict[str, Any]] = [] with path.open() as file: for line_number, line in enumerate(file, start=1): @@ -397,7 +449,9 @@ def _load_fact_rows(path: Path) -> tuple[dict[str, Any], ...]: if not stripped: continue try: - row = json.loads(stripped) + row = json.loads( + stripped, parse_float=LexicalFloat if lexical_floats else float + ) except json.JSONDecodeError as exc: raise ValueError( f"Invalid Ledger facts JSONL row {line_number}: {exc.msg}" diff --git a/packages/microcosm-build/src/microcosm/build/ledger_targets.py b/packages/microcosm-build/src/microcosm/build/ledger_targets.py index 3af241ca1c..035f18ad8a 100644 --- a/packages/microcosm-build/src/microcosm/build/ledger_targets.py +++ b/packages/microcosm-build/src/microcosm/build/ledger_targets.py @@ -20,6 +20,7 @@ from types import MappingProxyType from typing import Any +from microcosm.build.ledger_artifact import LexicalFloat from microcosm.calibrate import ( CalibrationHierarchy, CalibrationHierarchySeed, @@ -5058,7 +5059,9 @@ def _dimension_values_match(fact: object, expected: object) -> bool: def _strict_scalar_equal(actual: object, expected: object) -> bool: - return type(actual) is type(expected) and actual == expected + actual_type = float if type(actual) is LexicalFloat else type(actual) + expected_type = float if type(expected) is LexicalFloat else type(expected) + return actual_type is expected_type and actual == expected def _measure_concepts(fact: object) -> tuple[str, ...]: diff --git a/packages/microcosm-build/src/microcosm/build/nz/country_package.json b/packages/microcosm-build/src/microcosm/build/nz/country_package.json index 460fcef650..06fd0a27ef 100644 --- a/packages/microcosm-build/src/microcosm/build/nz/country_package.json +++ b/packages/microcosm-build/src/microcosm/build/nz/country_package.json @@ -102,6 +102,16 @@ "kind": "legacy_json", "schema_id": "legacy_json" }, + { + "path": "reference_aging.json", + "kind": "legacy_json", + "schema_id": "legacy_json" + }, + { + "path": "reference_intervals.json", + "kind": "legacy_json", + "schema_id": "legacy_json" + }, { "path": "reference_inventory.json", "kind": "legacy_json", diff --git a/packages/microcosm-build/src/microcosm/build/nz/reference_aging.json b/packages/microcosm-build/src/microcosm/build/nz/reference_aging.json new file mode 100644 index 0000000000..a82957f2a7 --- /dev/null +++ b/packages/microcosm-build/src/microcosm/build/nz/reference_aging.json @@ -0,0 +1,8386 @@ +{ + "schema_version": 1, + "feed_identity": { + "source_commit": "8f4cfd573c0d6f580d9c51cd67e8f449a42ed174", + "facts_sha256": "03f5ea0fe60e6dc93a135ab32cd5cd6ffb56388e702a4734cdb515a956e36b18", + "manifest_sha256": "1ea2d1eeb122275a9ce7f861ca3e20e21dd695772c04ce9d71114168e92fe053", + "artifact_schema_version": "policyengine_ledger.consumer_artifact.v2", + "consumer_fact_schema_versions": [ + "chronicle.consumer_fact.v4" + ], + "consumer_fact_schema_sha256": "d953306d6f01fbc64db4372d0262d3012ee590269f8a25b276b18dca0626c6a0", + "fact_row_count": 12368 + }, + "factors": [ + { + "declaration": { + "schema_version": 1, + "id": "ird_ty2024_to_ty2027_low", + "operation": "projected_period_average_ratio", + "operation_version": 1, + "purpose": "profile_input", + "feed_identity": { + "source_commit": "8f4cfd573c0d6f580d9c51cd67e8f449a42ed174", + "facts_sha256": "03f5ea0fe60e6dc93a135ab32cd5cd6ffb56388e702a4734cdb515a956e36b18", + "manifest_sha256": "1ea2d1eeb122275a9ce7f861ca3e20e21dd695772c04ce9d71114168e92fe053", + "artifact_schema_version": "policyengine_ledger.consumer_artifact.v2", + "consumer_fact_schema_versions": [ + "chronicle.consumer_fact.v4" + ], + "consumer_fact_schema_sha256": "d953306d6f01fbc64db4372d0262d3012ee590269f8a25b276b18dca0626c6a0", + "fact_row_count": 12368 + }, + "source_period": 2024, + "target_period": 2027, + "source_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:cfbce1343aa646fce0411631", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-04-01", + "end_date": "2023-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:f9f4f127d080fe2f06617947", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-07-01", + "end_date": "2023-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:fb5938810b7b37ae8534e5f7", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-10-01", + "end_date": "2023-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2024-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2024q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:854e91ec1dd95e396659ad8e", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2024-01-01", + "end_date": "2024-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 3 + } + ], + "target_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-04-01", + "end_date": "2026-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 0, + "projection_offset": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2026-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 1, + "projection_offset": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-10-01", + "end_date": "2026-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 2, + "projection_offset": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2027-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2027q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2027-01-01", + "end_date": "2027-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 3, + "projection_offset": 3 + } + ], + "growth": { + "selector": { + "source_name": "treasury", + "source_measure_id": "average_weekly_earnings_annual_percentage_change", + "source_concept": "treasury.prefu26.average_weekly_earnings_annual_percentage_change", + "entity_name": "government", + "period_type": "fiscal_year", + "period_value": 2026, + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "treasury.prefu26.average_weekly_earnings.fy2026", + "dimensions": [ + "earnings_component", + "publication_status" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "publication_status": "Forecast" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "assertion": "source_projection", + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts" + }, + "validation": { + "unit": "percent", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_vintage": "prefu_2026_09_29", + "entity_role": "forecaster", + "provenance_class": "model_output", + "assertion": "source_projection", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2027-06-30" + }, + "source_column_id": "year_ending_30_june_2027" + }, + "unit_multiplier": "0.01", + "scenario_delta": "-0.5", + "assertion_policy": "allow_source_projection", + "sensitivity_provenance": [ + "d1599: symmetric ±0.5 percentage-point Microcosm sensitivity; high is not a Treasury forecast path" + ] + }, + "subperiods_per_year": 4, + "projection_policy": "observed_preferred_latest_contiguous", + "rounding": { + "digits": 6, + "mode": "nearest_half_even" + }, + "expected_operational_factor": { + "numerator": 1115056, + "denominator": 1000000 + }, + "validity": { + "declared_on": "2026-10-23", + "valid_from": "2026-10-23", + "valid_until": "2026-11-03", + "as_of": "2026-10-23" + }, + "evidence": [ + "Stats NZ QES Table 7; QEMQ.SBSZ9A; ordinary-time FTE, all sectors, actual", + "Treasury PREFU 2026 Table 4.1; year ending 30 June 2027; Chronicle period 2026" + ], + "decision_references": [ + "d1599; IRD band ageing factors, 22 October 2026", + "G8-r2 hub rulings 3, 23 October 2026, sections 1–2" + ] + }, + "operational_factor": { + "numerator": 1115056, + "denominator": 1000000 + }, + "receipt": { + "schema_version": 1, + "operation": "projected_period_average_ratio", + "operation_version": 1, + "factor_id": "ird_ty2024_to_ty2027_low", + "declaration_sha256": "4325961ede06db69ec91791cc1addf49f889f277fd62791778754b28830bbcba", + "feed_identity": { + "source_commit": "8f4cfd573c0d6f580d9c51cd67e8f449a42ed174", + "facts_sha256": "03f5ea0fe60e6dc93a135ab32cd5cd6ffb56388e702a4734cdb515a956e36b18", + "manifest_sha256": "1ea2d1eeb122275a9ce7f861ca3e20e21dd695772c04ce9d71114168e92fe053", + "artifact_schema_version": "policyengine_ledger.consumer_artifact.v2", + "consumer_fact_schema_versions": [ + "chronicle.consumer_fact.v4" + ], + "consumer_fact_schema_sha256": "d953306d6f01fbc64db4372d0262d3012ee590269f8a25b276b18dca0626c6a0", + "fact_row_count": 12368 + }, + "source_period": 2024, + "target_period": 2027, + "source_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:cfbce1343aa646fce0411631", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:cfbce1343aa646fce0411631", + "decimal_operand": "1502.27", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1502.27", + "recovered_decimal": "1502.27", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-04-01", + "end_date": "2023-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2023-Q2" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2025-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_size_bytes": 135784, + "source_table": "Quarterly Employment Survey June 2025 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2025-quarter/Download-data/quarterly-employment-survey-june-2025-quarter.xlsx", + "vintage": "stats_nz_qes_june_2025" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2023-06-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Jun 2023 quarter", + "start_date": "2023-04-01" + }, + "weight": "1", + "sequence": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:f9f4f127d080fe2f06617947", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:f9f4f127d080fe2f06617947", + "decimal_operand": "1528.92", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1528.92", + "recovered_decimal": "1528.92", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-07-01", + "end_date": "2023-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2023-Q3" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2025-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_size_bytes": 135784, + "source_table": "Quarterly Employment Survey June 2025 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2025-quarter/Download-data/quarterly-employment-survey-june-2025-quarter.xlsx", + "vintage": "stats_nz_qes_june_2025" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2023-09-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Sep 2023 quarter", + "start_date": "2023-07-01" + }, + "weight": "1", + "sequence": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:fb5938810b7b37ae8534e5f7", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:fb5938810b7b37ae8534e5f7", + "decimal_operand": "1556.16", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1556.16", + "recovered_decimal": "1556.16", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-10-01", + "end_date": "2023-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2023-Q4" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2025-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_size_bytes": 135784, + "source_table": "Quarterly Employment Survey June 2025 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2025-quarter/Download-data/quarterly-employment-survey-june-2025-quarter.xlsx", + "vintage": "stats_nz_qes_june_2025" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2023-12-31", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Dec 2023 quarter", + "start_date": "2023-10-01" + }, + "weight": "1", + "sequence": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2024-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2024q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:854e91ec1dd95e396659ad8e", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:854e91ec1dd95e396659ad8e", + "decimal_operand": "1563.54", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1563.54", + "recovered_decimal": "1563.54", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2024-01-01", + "end_date": "2024-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2024-Q1" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2025-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_size_bytes": 135784, + "source_table": "Quarterly Employment Survey June 2025 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2025-quarter/Download-data/quarterly-employment-survey-june-2025-quarter.xlsx", + "vintage": "stats_nz_qes_june_2025" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2024-03-31", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Mar 2024 quarter", + "start_date": "2024-01-01" + }, + "weight": "1", + "sequence": 3 + } + ], + "target_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "decimal_operand": "1700.68", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1700.68", + "recovered_decimal": "1700.68", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-04-01", + "end_date": "2026-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2026-Q2" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2026-06-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Jun 2026 quarter", + "start_date": "2026-04-01" + }, + "status": "observed", + "sequence": 0, + "weight": "1", + "projection_offset": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2026-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 1, + "weight": "1", + "projection_offset": 1, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-10-01", + "end_date": "2026-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 2, + "weight": "1", + "projection_offset": 2, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2027-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2027q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2027-01-01", + "end_date": "2027-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 3, + "weight": "1", + "projection_offset": 3, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + } + ], + "subperiods_per_year": 4, + "projection_policy": "observed_preferred_latest_contiguous", + "denominator_mean": { + "numerator": 615089, + "denominator": 400 + }, + "growth": { + "selector": { + "source_name": "treasury", + "source_measure_id": "average_weekly_earnings_annual_percentage_change", + "source_concept": "treasury.prefu26.average_weekly_earnings_annual_percentage_change", + "entity_name": "government", + "period_type": "fiscal_year", + "period_value": 2026, + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "treasury.prefu26.average_weekly_earnings.fy2026", + "dimensions": [ + "earnings_component", + "publication_status" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "publication_status": "Forecast" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "assertion": "source_projection", + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "decimal_operand": "2.7", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "2.7", + "recovered_decimal": "2.7", + "decimal_values_equal": true + }, + "validation": { + "unit": "percent", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_vintage": "prefu_2026_09_29", + "entity_role": "forecaster", + "provenance_class": "model_output", + "assertion": "source_projection", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2027-06-30" + }, + "source_column_id": "year_ending_30_june_2027" + }, + "period": { + "type": "fiscal_year", + "value": 2026 + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/treasury/treasury-prefu26-economic-assumptions/2026/e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9/prefu26-charts-data.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/treasury/treasury-prefu26-economic-assumptions/2026/e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9/prefu26-charts-data.xlsx", + "source_file": "prefu26-charts-data.xlsx", + "source_name": "treasury", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_size_bytes": 664670, + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts", + "url": "https://www.treasury.govt.nz/sites/default/files/2026-09/prefu26-charts-data.xlsx", + "vintage": "prefu_2026_09_29" + }, + "unit": "percent", + "assertion": "source_projection", + "provenance_class": "model_output", + "entity_role": "forecaster", + "period_coverage": { + "basis": "fiscal", + "end_date": "2027-06-30", + "notes": "Publisher Year ending 30 June 2027; Chronicle opening-year fiscal_year:2026. Publisher column status is Forecast. Footnote 3 (Table 4.1!C21:D21): Ordinary time. Footnote 4 (C22:D22): Measures are actuals except for real GDP and nominal GDP. 2026 earnings are therefore actuals despite the Forecast4 column heading; only 2027–2031 earnings are forecasts. The published annual percentage change is retained unchanged; no annual average, level, factor or period alignment is calculated.", + "source_period_label": "Year ending 30 June 2027", + "start_date": "2026-07-01" + }, + "unit_multiplier": "0.01", + "scenario_delta": "-0.5", + "sensitivity_provenance": [ + "d1599: symmetric ±0.5 percentage-point Microcosm sensitivity; high is not a Treasury forecast path" + ], + "effective_growth": { + "numerator": 11, + "denominator": 500 + } + }, + "root_bounds": { + "lower": { + "numerator": 50272759932393, + "denominator": 50000000000000 + }, + "upper": { + "numerator": 100545519864787, + "denominator": 100000000000000 + }, + "exact": false, + "decimal_places": 14, + "degree": 4, + "radicand": { + "numerator": 511, + "denominator": 500 + } + }, + "numerator_mean_bounds": { + "lower": { + "numerator": 21433087509261019469100089110351817978329164269, + "denominator": 12500000000000000000000000000000000000000000 + }, + "upper": { + "numerator": 171464700074090725365853333139754513013059781351, + "denominator": 100000000000000000000000000000000000000000000 + } + }, + "unrounded_factor_bounds": { + "lower": { + "numerator": 21433087509261019469100089110351817978329164269, + "denominator": 19221531250000000000000000000000000000000000000 + }, + "upper": { + "numerator": 171464700074090725365853333139754513013059781351, + "denominator": 153772250000000000000000000000000000000000000000 + } + }, + "rounding": { + "digits": 6, + "mode": "nearest_half_even" + }, + "operational_factor": { + "numerator": 1115056, + "denominator": 1000000 + }, + "validity": { + "declared_on": "2026-10-23", + "valid_from": "2026-10-23", + "valid_until": "2026-11-03", + "as_of": "2026-10-23" + }, + "evidence": [ + "Stats NZ QES Table 7; QEMQ.SBSZ9A; ordinary-time FTE, all sectors, actual", + "Treasury PREFU 2026 Table 4.1; year ending 30 June 2027; Chronicle period 2026" + ], + "decision_references": [ + "d1599; IRD band ageing factors, 22 October 2026", + "G8-r2 hub rulings 3, 23 October 2026, sections 1–2" + ], + "receipt_sha256": "beb087aeff370b0de497abb10ea2558533ca9a9995b556dc1d63d70327ad3885" + } + }, + { + "declaration": { + "schema_version": 1, + "id": "ird_ty2024_to_ty2027_central", + "operation": "projected_period_average_ratio", + "operation_version": 1, + "purpose": "profile_input", + "feed_identity": { + "source_commit": "8f4cfd573c0d6f580d9c51cd67e8f449a42ed174", + "facts_sha256": "03f5ea0fe60e6dc93a135ab32cd5cd6ffb56388e702a4734cdb515a956e36b18", + "manifest_sha256": "1ea2d1eeb122275a9ce7f861ca3e20e21dd695772c04ce9d71114168e92fe053", + "artifact_schema_version": "policyengine_ledger.consumer_artifact.v2", + "consumer_fact_schema_versions": [ + "chronicle.consumer_fact.v4" + ], + "consumer_fact_schema_sha256": "d953306d6f01fbc64db4372d0262d3012ee590269f8a25b276b18dca0626c6a0", + "fact_row_count": 12368 + }, + "source_period": 2024, + "target_period": 2027, + "source_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:cfbce1343aa646fce0411631", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-04-01", + "end_date": "2023-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:f9f4f127d080fe2f06617947", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-07-01", + "end_date": "2023-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:fb5938810b7b37ae8534e5f7", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-10-01", + "end_date": "2023-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2024-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2024q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:854e91ec1dd95e396659ad8e", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2024-01-01", + "end_date": "2024-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 3 + } + ], + "target_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-04-01", + "end_date": "2026-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 0, + "projection_offset": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2026-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 1, + "projection_offset": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-10-01", + "end_date": "2026-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 2, + "projection_offset": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2027-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2027q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2027-01-01", + "end_date": "2027-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 3, + "projection_offset": 3 + } + ], + "growth": { + "selector": { + "source_name": "treasury", + "source_measure_id": "average_weekly_earnings_annual_percentage_change", + "source_concept": "treasury.prefu26.average_weekly_earnings_annual_percentage_change", + "entity_name": "government", + "period_type": "fiscal_year", + "period_value": 2026, + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "treasury.prefu26.average_weekly_earnings.fy2026", + "dimensions": [ + "earnings_component", + "publication_status" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "publication_status": "Forecast" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "assertion": "source_projection", + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts" + }, + "validation": { + "unit": "percent", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_vintage": "prefu_2026_09_29", + "entity_role": "forecaster", + "provenance_class": "model_output", + "assertion": "source_projection", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2027-06-30" + }, + "source_column_id": "year_ending_30_june_2027" + }, + "unit_multiplier": "0.01", + "scenario_delta": "0", + "assertion_policy": "allow_source_projection", + "sensitivity_provenance": [ + "d1599: symmetric ±0.5 percentage-point Microcosm sensitivity; high is not a Treasury forecast path" + ] + }, + "subperiods_per_year": 4, + "projection_policy": "observed_preferred_latest_contiguous", + "rounding": { + "digits": 6, + "mode": "nearest_half_even" + }, + "expected_operational_factor": { + "numerator": 1117109, + "denominator": 1000000 + }, + "validity": { + "declared_on": "2026-10-23", + "valid_from": "2026-10-23", + "valid_until": "2026-11-03", + "as_of": "2026-10-23" + }, + "evidence": [ + "Stats NZ QES Table 7; QEMQ.SBSZ9A; ordinary-time FTE, all sectors, actual", + "Treasury PREFU 2026 Table 4.1; year ending 30 June 2027; Chronicle period 2026" + ], + "decision_references": [ + "d1599; IRD band ageing factors, 22 October 2026", + "G8-r2 hub rulings 3, 23 October 2026, sections 1–2" + ] + }, + "operational_factor": { + "numerator": 1117109, + "denominator": 1000000 + }, + "receipt": { + "schema_version": 1, + "operation": "projected_period_average_ratio", + "operation_version": 1, + "factor_id": "ird_ty2024_to_ty2027_central", + "declaration_sha256": "4178ab3ea62899cad556170195b74dbb41faf7ff7cde57e298d1e62447b1b004", + "feed_identity": { + "source_commit": "8f4cfd573c0d6f580d9c51cd67e8f449a42ed174", + "facts_sha256": "03f5ea0fe60e6dc93a135ab32cd5cd6ffb56388e702a4734cdb515a956e36b18", + "manifest_sha256": "1ea2d1eeb122275a9ce7f861ca3e20e21dd695772c04ce9d71114168e92fe053", + "artifact_schema_version": "policyengine_ledger.consumer_artifact.v2", + "consumer_fact_schema_versions": [ + "chronicle.consumer_fact.v4" + ], + "consumer_fact_schema_sha256": "d953306d6f01fbc64db4372d0262d3012ee590269f8a25b276b18dca0626c6a0", + "fact_row_count": 12368 + }, + "source_period": 2024, + "target_period": 2027, + "source_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:cfbce1343aa646fce0411631", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:cfbce1343aa646fce0411631", + "decimal_operand": "1502.27", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1502.27", + "recovered_decimal": "1502.27", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-04-01", + "end_date": "2023-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2023-Q2" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2025-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_size_bytes": 135784, + "source_table": "Quarterly Employment Survey June 2025 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2025-quarter/Download-data/quarterly-employment-survey-june-2025-quarter.xlsx", + "vintage": "stats_nz_qes_june_2025" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2023-06-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Jun 2023 quarter", + "start_date": "2023-04-01" + }, + "weight": "1", + "sequence": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:f9f4f127d080fe2f06617947", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:f9f4f127d080fe2f06617947", + "decimal_operand": "1528.92", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1528.92", + "recovered_decimal": "1528.92", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-07-01", + "end_date": "2023-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2023-Q3" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2025-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_size_bytes": 135784, + "source_table": "Quarterly Employment Survey June 2025 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2025-quarter/Download-data/quarterly-employment-survey-june-2025-quarter.xlsx", + "vintage": "stats_nz_qes_june_2025" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2023-09-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Sep 2023 quarter", + "start_date": "2023-07-01" + }, + "weight": "1", + "sequence": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:fb5938810b7b37ae8534e5f7", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:fb5938810b7b37ae8534e5f7", + "decimal_operand": "1556.16", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1556.16", + "recovered_decimal": "1556.16", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-10-01", + "end_date": "2023-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2023-Q4" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2025-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_size_bytes": 135784, + "source_table": "Quarterly Employment Survey June 2025 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2025-quarter/Download-data/quarterly-employment-survey-june-2025-quarter.xlsx", + "vintage": "stats_nz_qes_june_2025" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2023-12-31", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Dec 2023 quarter", + "start_date": "2023-10-01" + }, + "weight": "1", + "sequence": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2024-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2024q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:854e91ec1dd95e396659ad8e", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:854e91ec1dd95e396659ad8e", + "decimal_operand": "1563.54", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1563.54", + "recovered_decimal": "1563.54", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2024-01-01", + "end_date": "2024-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2024-Q1" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2025-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_size_bytes": 135784, + "source_table": "Quarterly Employment Survey June 2025 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2025-quarter/Download-data/quarterly-employment-survey-june-2025-quarter.xlsx", + "vintage": "stats_nz_qes_june_2025" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2024-03-31", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Mar 2024 quarter", + "start_date": "2024-01-01" + }, + "weight": "1", + "sequence": 3 + } + ], + "target_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "decimal_operand": "1700.68", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1700.68", + "recovered_decimal": "1700.68", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-04-01", + "end_date": "2026-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2026-Q2" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2026-06-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Jun 2026 quarter", + "start_date": "2026-04-01" + }, + "status": "observed", + "sequence": 0, + "weight": "1", + "projection_offset": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2026-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 1, + "weight": "1", + "projection_offset": 1, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-10-01", + "end_date": "2026-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 2, + "weight": "1", + "projection_offset": 2, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2027-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2027q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2027-01-01", + "end_date": "2027-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 3, + "weight": "1", + "projection_offset": 3, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + } + ], + "subperiods_per_year": 4, + "projection_policy": "observed_preferred_latest_contiguous", + "denominator_mean": { + "numerator": 615089, + "denominator": 400 + }, + "growth": { + "selector": { + "source_name": "treasury", + "source_measure_id": "average_weekly_earnings_annual_percentage_change", + "source_concept": "treasury.prefu26.average_weekly_earnings_annual_percentage_change", + "entity_name": "government", + "period_type": "fiscal_year", + "period_value": 2026, + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "treasury.prefu26.average_weekly_earnings.fy2026", + "dimensions": [ + "earnings_component", + "publication_status" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "publication_status": "Forecast" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "assertion": "source_projection", + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "decimal_operand": "2.7", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "2.7", + "recovered_decimal": "2.7", + "decimal_values_equal": true + }, + "validation": { + "unit": "percent", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_vintage": "prefu_2026_09_29", + "entity_role": "forecaster", + "provenance_class": "model_output", + "assertion": "source_projection", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2027-06-30" + }, + "source_column_id": "year_ending_30_june_2027" + }, + "period": { + "type": "fiscal_year", + "value": 2026 + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/treasury/treasury-prefu26-economic-assumptions/2026/e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9/prefu26-charts-data.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/treasury/treasury-prefu26-economic-assumptions/2026/e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9/prefu26-charts-data.xlsx", + "source_file": "prefu26-charts-data.xlsx", + "source_name": "treasury", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_size_bytes": 664670, + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts", + "url": "https://www.treasury.govt.nz/sites/default/files/2026-09/prefu26-charts-data.xlsx", + "vintage": "prefu_2026_09_29" + }, + "unit": "percent", + "assertion": "source_projection", + "provenance_class": "model_output", + "entity_role": "forecaster", + "period_coverage": { + "basis": "fiscal", + "end_date": "2027-06-30", + "notes": "Publisher Year ending 30 June 2027; Chronicle opening-year fiscal_year:2026. Publisher column status is Forecast. Footnote 3 (Table 4.1!C21:D21): Ordinary time. Footnote 4 (C22:D22): Measures are actuals except for real GDP and nominal GDP. 2026 earnings are therefore actuals despite the Forecast4 column heading; only 2027–2031 earnings are forecasts. The published annual percentage change is retained unchanged; no annual average, level, factor or period alignment is calculated.", + "source_period_label": "Year ending 30 June 2027", + "start_date": "2026-07-01" + }, + "unit_multiplier": "0.01", + "scenario_delta": "0", + "sensitivity_provenance": [ + "d1599: symmetric ±0.5 percentage-point Microcosm sensitivity; high is not a Treasury forecast path" + ], + "effective_growth": { + "numerator": 27, + "denominator": 1000 + } + }, + "root_bounds": { + "lower": { + "numerator": 100668271307927, + "denominator": 100000000000000 + }, + "upper": { + "numerator": 12583533913491, + "denominator": 12500000000000 + }, + "exact": false, + "decimal_places": 14, + "degree": 4, + "radicand": { + "numerator": 1027, + "denominator": 1000 + } + }, + "numerator_mean_bounds": { + "lower": { + "numerator": 171780381168748188591006079321988113950935096211, + "denominator": 100000000000000000000000000000000000000000000 + }, + "upper": { + "numerator": 335508556970216332809143747140199880884173607, + "denominator": 195312500000000000000000000000000000000000 + } + }, + "unrounded_factor_bounds": { + "lower": { + "numerator": 171780381168748188591006079321988113950935096211, + "denominator": 153772250000000000000000000000000000000000000000 + }, + "upper": { + "numerator": 335508556970216332809143747140199880884173607, + "denominator": 300336425781250000000000000000000000000000000 + } + }, + "rounding": { + "digits": 6, + "mode": "nearest_half_even" + }, + "operational_factor": { + "numerator": 1117109, + "denominator": 1000000 + }, + "validity": { + "declared_on": "2026-10-23", + "valid_from": "2026-10-23", + "valid_until": "2026-11-03", + "as_of": "2026-10-23" + }, + "evidence": [ + "Stats NZ QES Table 7; QEMQ.SBSZ9A; ordinary-time FTE, all sectors, actual", + "Treasury PREFU 2026 Table 4.1; year ending 30 June 2027; Chronicle period 2026" + ], + "decision_references": [ + "d1599; IRD band ageing factors, 22 October 2026", + "G8-r2 hub rulings 3, 23 October 2026, sections 1–2" + ], + "receipt_sha256": "6234283ef363388578f13d7833faf0c6eb0ea1743ecc66333d017e59c554a798" + } + }, + { + "declaration": { + "schema_version": 1, + "id": "ird_ty2024_to_ty2027_high", + "operation": "projected_period_average_ratio", + "operation_version": 1, + "purpose": "profile_input", + "feed_identity": { + "source_commit": "8f4cfd573c0d6f580d9c51cd67e8f449a42ed174", + "facts_sha256": "03f5ea0fe60e6dc93a135ab32cd5cd6ffb56388e702a4734cdb515a956e36b18", + "manifest_sha256": "1ea2d1eeb122275a9ce7f861ca3e20e21dd695772c04ce9d71114168e92fe053", + "artifact_schema_version": "policyengine_ledger.consumer_artifact.v2", + "consumer_fact_schema_versions": [ + "chronicle.consumer_fact.v4" + ], + "consumer_fact_schema_sha256": "d953306d6f01fbc64db4372d0262d3012ee590269f8a25b276b18dca0626c6a0", + "fact_row_count": 12368 + }, + "source_period": 2024, + "target_period": 2027, + "source_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:cfbce1343aa646fce0411631", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-04-01", + "end_date": "2023-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:f9f4f127d080fe2f06617947", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-07-01", + "end_date": "2023-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:fb5938810b7b37ae8534e5f7", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-10-01", + "end_date": "2023-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2024-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2024q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:854e91ec1dd95e396659ad8e", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2024-01-01", + "end_date": "2024-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 3 + } + ], + "target_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-04-01", + "end_date": "2026-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 0, + "projection_offset": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2026-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 1, + "projection_offset": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-10-01", + "end_date": "2026-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 2, + "projection_offset": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2027-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2027q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2027-01-01", + "end_date": "2027-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 3, + "projection_offset": 3 + } + ], + "growth": { + "selector": { + "source_name": "treasury", + "source_measure_id": "average_weekly_earnings_annual_percentage_change", + "source_concept": "treasury.prefu26.average_weekly_earnings_annual_percentage_change", + "entity_name": "government", + "period_type": "fiscal_year", + "period_value": 2026, + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "treasury.prefu26.average_weekly_earnings.fy2026", + "dimensions": [ + "earnings_component", + "publication_status" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "publication_status": "Forecast" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "assertion": "source_projection", + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts" + }, + "validation": { + "unit": "percent", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_vintage": "prefu_2026_09_29", + "entity_role": "forecaster", + "provenance_class": "model_output", + "assertion": "source_projection", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2027-06-30" + }, + "source_column_id": "year_ending_30_june_2027" + }, + "unit_multiplier": "0.01", + "scenario_delta": "0.5", + "assertion_policy": "allow_source_projection", + "sensitivity_provenance": [ + "d1599: symmetric ±0.5 percentage-point Microcosm sensitivity; high is not a Treasury forecast path" + ] + }, + "subperiods_per_year": 4, + "projection_policy": "observed_preferred_latest_contiguous", + "rounding": { + "digits": 6, + "mode": "nearest_half_even" + }, + "expected_operational_factor": { + "numerator": 1119158, + "denominator": 1000000 + }, + "validity": { + "declared_on": "2026-10-23", + "valid_from": "2026-10-23", + "valid_until": "2026-11-03", + "as_of": "2026-10-23" + }, + "evidence": [ + "Stats NZ QES Table 7; QEMQ.SBSZ9A; ordinary-time FTE, all sectors, actual", + "Treasury PREFU 2026 Table 4.1; year ending 30 June 2027; Chronicle period 2026" + ], + "decision_references": [ + "d1599; IRD band ageing factors, 22 October 2026", + "G8-r2 hub rulings 3, 23 October 2026, sections 1–2" + ] + }, + "operational_factor": { + "numerator": 1119158, + "denominator": 1000000 + }, + "receipt": { + "schema_version": 1, + "operation": "projected_period_average_ratio", + "operation_version": 1, + "factor_id": "ird_ty2024_to_ty2027_high", + "declaration_sha256": "29b91c04a391e207e627f99de7e7bdeb90fc0c5d0c1558bccc4a76c3731e801d", + "feed_identity": { + "source_commit": "8f4cfd573c0d6f580d9c51cd67e8f449a42ed174", + "facts_sha256": "03f5ea0fe60e6dc93a135ab32cd5cd6ffb56388e702a4734cdb515a956e36b18", + "manifest_sha256": "1ea2d1eeb122275a9ce7f861ca3e20e21dd695772c04ce9d71114168e92fe053", + "artifact_schema_version": "policyengine_ledger.consumer_artifact.v2", + "consumer_fact_schema_versions": [ + "chronicle.consumer_fact.v4" + ], + "consumer_fact_schema_sha256": "d953306d6f01fbc64db4372d0262d3012ee590269f8a25b276b18dca0626c6a0", + "fact_row_count": 12368 + }, + "source_period": 2024, + "target_period": 2027, + "source_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:cfbce1343aa646fce0411631", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:cfbce1343aa646fce0411631", + "decimal_operand": "1502.27", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1502.27", + "recovered_decimal": "1502.27", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-04-01", + "end_date": "2023-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2023-Q2" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2025-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_size_bytes": 135784, + "source_table": "Quarterly Employment Survey June 2025 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2025-quarter/Download-data/quarterly-employment-survey-june-2025-quarter.xlsx", + "vintage": "stats_nz_qes_june_2025" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2023-06-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Jun 2023 quarter", + "start_date": "2023-04-01" + }, + "weight": "1", + "sequence": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:f9f4f127d080fe2f06617947", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:f9f4f127d080fe2f06617947", + "decimal_operand": "1528.92", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1528.92", + "recovered_decimal": "1528.92", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-07-01", + "end_date": "2023-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2023-Q3" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2025-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_size_bytes": 135784, + "source_table": "Quarterly Employment Survey June 2025 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2025-quarter/Download-data/quarterly-employment-survey-june-2025-quarter.xlsx", + "vintage": "stats_nz_qes_june_2025" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2023-09-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Sep 2023 quarter", + "start_date": "2023-07-01" + }, + "weight": "1", + "sequence": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:fb5938810b7b37ae8534e5f7", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:fb5938810b7b37ae8534e5f7", + "decimal_operand": "1556.16", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1556.16", + "recovered_decimal": "1556.16", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-10-01", + "end_date": "2023-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2023-Q4" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2025-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_size_bytes": 135784, + "source_table": "Quarterly Employment Survey June 2025 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2025-quarter/Download-data/quarterly-employment-survey-june-2025-quarter.xlsx", + "vintage": "stats_nz_qes_june_2025" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2023-12-31", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Dec 2023 quarter", + "start_date": "2023-10-01" + }, + "weight": "1", + "sequence": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2024-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2024q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:854e91ec1dd95e396659ad8e", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:854e91ec1dd95e396659ad8e", + "decimal_operand": "1563.54", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1563.54", + "recovered_decimal": "1563.54", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2024-01-01", + "end_date": "2024-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2024-Q1" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2025-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_size_bytes": 135784, + "source_table": "Quarterly Employment Survey June 2025 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2025-quarter/Download-data/quarterly-employment-survey-june-2025-quarter.xlsx", + "vintage": "stats_nz_qes_june_2025" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2024-03-31", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Mar 2024 quarter", + "start_date": "2024-01-01" + }, + "weight": "1", + "sequence": 3 + } + ], + "target_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "decimal_operand": "1700.68", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1700.68", + "recovered_decimal": "1700.68", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-04-01", + "end_date": "2026-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2026-Q2" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2026-06-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Jun 2026 quarter", + "start_date": "2026-04-01" + }, + "status": "observed", + "sequence": 0, + "weight": "1", + "projection_offset": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2026-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 1, + "weight": "1", + "projection_offset": 1, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-10-01", + "end_date": "2026-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 2, + "weight": "1", + "projection_offset": 2, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2027-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2027q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2027-01-01", + "end_date": "2027-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 3, + "weight": "1", + "projection_offset": 3, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + } + ], + "subperiods_per_year": 4, + "projection_policy": "observed_preferred_latest_contiguous", + "denominator_mean": { + "numerator": 615089, + "denominator": 400 + }, + "growth": { + "selector": { + "source_name": "treasury", + "source_measure_id": "average_weekly_earnings_annual_percentage_change", + "source_concept": "treasury.prefu26.average_weekly_earnings_annual_percentage_change", + "entity_name": "government", + "period_type": "fiscal_year", + "period_value": 2026, + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "treasury.prefu26.average_weekly_earnings.fy2026", + "dimensions": [ + "earnings_component", + "publication_status" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "publication_status": "Forecast" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "assertion": "source_projection", + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "decimal_operand": "2.7", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "2.7", + "recovered_decimal": "2.7", + "decimal_values_equal": true + }, + "validation": { + "unit": "percent", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_vintage": "prefu_2026_09_29", + "entity_role": "forecaster", + "provenance_class": "model_output", + "assertion": "source_projection", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2027-06-30" + }, + "source_column_id": "year_ending_30_june_2027" + }, + "period": { + "type": "fiscal_year", + "value": 2026 + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/treasury/treasury-prefu26-economic-assumptions/2026/e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9/prefu26-charts-data.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/treasury/treasury-prefu26-economic-assumptions/2026/e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9/prefu26-charts-data.xlsx", + "source_file": "prefu26-charts-data.xlsx", + "source_name": "treasury", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_size_bytes": 664670, + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts", + "url": "https://www.treasury.govt.nz/sites/default/files/2026-09/prefu26-charts-data.xlsx", + "vintage": "prefu_2026_09_29" + }, + "unit": "percent", + "assertion": "source_projection", + "provenance_class": "model_output", + "entity_role": "forecaster", + "period_coverage": { + "basis": "fiscal", + "end_date": "2027-06-30", + "notes": "Publisher Year ending 30 June 2027; Chronicle opening-year fiscal_year:2026. Publisher column status is Forecast. Footnote 3 (Table 4.1!C21:D21): Ordinary time. Footnote 4 (C22:D22): Measures are actuals except for real GDP and nominal GDP. 2026 earnings are therefore actuals despite the Forecast4 column heading; only 2027–2031 earnings are forecasts. The published annual percentage change is retained unchanged; no annual average, level, factor or period alignment is calculated.", + "source_period_label": "Year ending 30 June 2027", + "start_date": "2026-07-01" + }, + "unit_multiplier": "0.01", + "scenario_delta": "0.5", + "sensitivity_provenance": [ + "d1599: symmetric ±0.5 percentage-point Microcosm sensitivity; high is not a Treasury forecast path" + ], + "effective_growth": { + "numerator": 4, + "denominator": 125 + } + }, + "root_bounds": { + "lower": { + "numerator": 100790575349881, + "denominator": 100000000000000 + }, + "upper": { + "numerator": 50395287674941, + "denominator": 50000000000000 + }, + "exact": false, + "decimal_places": 14, + "degree": 4, + "radicand": { + "numerator": 129, + "denominator": 125 + } + }, + "numerator_mean_bounds": { + "lower": { + "numerator": 172095423947015521933465483088234150187075944797, + "denominator": 100000000000000000000000000000000000000000000 + }, + "upper": { + "numerator": 21511927993377262490437471966978882670435826057, + "denominator": 12500000000000000000000000000000000000000000 + } + }, + "unrounded_factor_bounds": { + "lower": { + "numerator": 172095423947015521933465483088234150187075944797, + "denominator": 153772250000000000000000000000000000000000000000 + }, + "upper": { + "numerator": 21511927993377262490437471966978882670435826057, + "denominator": 19221531250000000000000000000000000000000000000 + } + }, + "rounding": { + "digits": 6, + "mode": "nearest_half_even" + }, + "operational_factor": { + "numerator": 1119158, + "denominator": 1000000 + }, + "validity": { + "declared_on": "2026-10-23", + "valid_from": "2026-10-23", + "valid_until": "2026-11-03", + "as_of": "2026-10-23" + }, + "evidence": [ + "Stats NZ QES Table 7; QEMQ.SBSZ9A; ordinary-time FTE, all sectors, actual", + "Treasury PREFU 2026 Table 4.1; year ending 30 June 2027; Chronicle period 2026" + ], + "decision_references": [ + "d1599; IRD band ageing factors, 22 October 2026", + "G8-r2 hub rulings 3, 23 October 2026, sections 1–2" + ], + "receipt_sha256": "cc047908112d30352a300efd495c5ace4a697e93d7f21dcd4f53a7cdb175db3f" + } + }, + { + "declaration": { + "schema_version": 1, + "id": "p1_ty2026_to_ty2027_low", + "operation": "projected_period_average_ratio", + "operation_version": 1, + "purpose": "profile_input", + "feed_identity": { + "source_commit": "8f4cfd573c0d6f580d9c51cd67e8f449a42ed174", + "facts_sha256": "03f5ea0fe60e6dc93a135ab32cd5cd6ffb56388e702a4734cdb515a956e36b18", + "manifest_sha256": "1ea2d1eeb122275a9ce7f861ca3e20e21dd695772c04ce9d71114168e92fe053", + "artifact_schema_version": "policyengine_ledger.consumer_artifact.v2", + "consumer_fact_schema_versions": [ + "chronicle.consumer_fact.v4" + ], + "consumer_fact_schema_sha256": "d953306d6f01fbc64db4372d0262d3012ee590269f8a25b276b18dca0626c6a0", + "fact_row_count": 12368 + }, + "source_period": 2026, + "target_period": 2027, + "source_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:86ce22ba42a6e2a36b889f9b", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-04-01", + "end_date": "2025-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:434e7b2736b4b16589034c72", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-07-01", + "end_date": "2025-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:bc87e53157eaf53c846879dc", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-10-01", + "end_date": "2025-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:78e735569814069f8066ba9f", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-01-01", + "end_date": "2026-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 3 + } + ], + "target_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-04-01", + "end_date": "2026-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 0, + "projection_offset": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2026-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 1, + "projection_offset": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-10-01", + "end_date": "2026-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 2, + "projection_offset": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2027-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2027q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2027-01-01", + "end_date": "2027-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 3, + "projection_offset": 3 + } + ], + "growth": { + "selector": { + "source_name": "treasury", + "source_measure_id": "average_weekly_earnings_annual_percentage_change", + "source_concept": "treasury.prefu26.average_weekly_earnings_annual_percentage_change", + "entity_name": "government", + "period_type": "fiscal_year", + "period_value": 2026, + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "treasury.prefu26.average_weekly_earnings.fy2026", + "dimensions": [ + "earnings_component", + "publication_status" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "publication_status": "Forecast" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "assertion": "source_projection", + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts" + }, + "validation": { + "unit": "percent", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_vintage": "prefu_2026_09_29", + "entity_role": "forecaster", + "provenance_class": "model_output", + "assertion": "source_projection", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2027-06-30" + }, + "source_column_id": "year_ending_30_june_2027" + }, + "unit_multiplier": "0.01", + "scenario_delta": "-0.5", + "assertion_policy": "allow_source_projection", + "sensitivity_provenance": [ + "d1599: symmetric ±0.5 percentage-point Microcosm sensitivity; high is not a Treasury forecast path" + ] + }, + "subperiods_per_year": 4, + "projection_policy": "observed_preferred_latest_contiguous", + "rounding": { + "digits": 6, + "mode": "nearest_half_even" + }, + "expected_operational_factor": { + "numerator": 1026690, + "denominator": 1000000 + }, + "validity": { + "declared_on": "2026-10-23", + "valid_from": "2026-10-23", + "valid_until": "2026-11-03", + "as_of": "2026-10-23" + }, + "evidence": [ + "Stats NZ QES Table 7; QEMQ.SBSZ9A; ordinary-time FTE, all sectors, actual", + "Treasury PREFU 2026 Table 4.1; year ending 30 June 2027; Chronicle period 2026" + ], + "decision_references": [ + "d1599; IRD band ageing factors, 22 October 2026", + "G8-r2 hub rulings 3, 23 October 2026, sections 1–2" + ] + }, + "operational_factor": { + "numerator": 1026690, + "denominator": 1000000 + }, + "receipt": { + "schema_version": 1, + "operation": "projected_period_average_ratio", + "operation_version": 1, + "factor_id": "p1_ty2026_to_ty2027_low", + "declaration_sha256": "53b22d7900851e896cf6ac17c9ca9f9bb92d436637459b8b59c513397833813e", + "feed_identity": { + "source_commit": "8f4cfd573c0d6f580d9c51cd67e8f449a42ed174", + "facts_sha256": "03f5ea0fe60e6dc93a135ab32cd5cd6ffb56388e702a4734cdb515a956e36b18", + "manifest_sha256": "1ea2d1eeb122275a9ce7f861ca3e20e21dd695772c04ce9d71114168e92fe053", + "artifact_schema_version": "policyengine_ledger.consumer_artifact.v2", + "consumer_fact_schema_versions": [ + "chronicle.consumer_fact.v4" + ], + "consumer_fact_schema_sha256": "d953306d6f01fbc64db4372d0262d3012ee590269f8a25b276b18dca0626c6a0", + "fact_row_count": 12368 + }, + "source_period": 2026, + "target_period": 2027, + "source_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:86ce22ba42a6e2a36b889f9b", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:86ce22ba42a6e2a36b889f9b", + "decimal_operand": "1652.72", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1652.72", + "recovered_decimal": "1652.72", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-04-01", + "end_date": "2025-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2025-Q2" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2025-06-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Jun 2025 quarter", + "start_date": "2025-04-01" + }, + "weight": "1", + "sequence": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:434e7b2736b4b16589034c72", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:434e7b2736b4b16589034c72", + "decimal_operand": "1661.12", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1661.12", + "recovered_decimal": "1661.12", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-07-01", + "end_date": "2025-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2025-Q3" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2025-09-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Sep 2025 quarter", + "start_date": "2025-07-01" + }, + "weight": "1", + "sequence": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:bc87e53157eaf53c846879dc", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:bc87e53157eaf53c846879dc", + "decimal_operand": "1681.06", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1681.06", + "recovered_decimal": "1681.06", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-10-01", + "end_date": "2025-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2025-Q4" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2025-12-31", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Dec 2025 quarter", + "start_date": "2025-10-01" + }, + "weight": "1", + "sequence": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:78e735569814069f8066ba9f", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:78e735569814069f8066ba9f", + "decimal_operand": "1685.39", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1685.39", + "recovered_decimal": "1685.39", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-01-01", + "end_date": "2026-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2026-Q1" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2026-03-31", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Mar 2026 quarter", + "start_date": "2026-01-01" + }, + "weight": "1", + "sequence": 3 + } + ], + "target_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "decimal_operand": "1700.68", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1700.68", + "recovered_decimal": "1700.68", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-04-01", + "end_date": "2026-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2026-Q2" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2026-06-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Jun 2026 quarter", + "start_date": "2026-04-01" + }, + "status": "observed", + "sequence": 0, + "weight": "1", + "projection_offset": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2026-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 1, + "weight": "1", + "projection_offset": 1, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-10-01", + "end_date": "2026-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 2, + "weight": "1", + "projection_offset": 2, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2027-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2027q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2027-01-01", + "end_date": "2027-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 3, + "weight": "1", + "projection_offset": 3, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + } + ], + "subperiods_per_year": 4, + "projection_policy": "observed_preferred_latest_contiguous", + "denominator_mean": { + "numerator": 668029, + "denominator": 400 + }, + "growth": { + "selector": { + "source_name": "treasury", + "source_measure_id": "average_weekly_earnings_annual_percentage_change", + "source_concept": "treasury.prefu26.average_weekly_earnings_annual_percentage_change", + "entity_name": "government", + "period_type": "fiscal_year", + "period_value": 2026, + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "treasury.prefu26.average_weekly_earnings.fy2026", + "dimensions": [ + "earnings_component", + "publication_status" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "publication_status": "Forecast" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "assertion": "source_projection", + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "decimal_operand": "2.7", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "2.7", + "recovered_decimal": "2.7", + "decimal_values_equal": true + }, + "validation": { + "unit": "percent", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_vintage": "prefu_2026_09_29", + "entity_role": "forecaster", + "provenance_class": "model_output", + "assertion": "source_projection", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2027-06-30" + }, + "source_column_id": "year_ending_30_june_2027" + }, + "period": { + "type": "fiscal_year", + "value": 2026 + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/treasury/treasury-prefu26-economic-assumptions/2026/e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9/prefu26-charts-data.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/treasury/treasury-prefu26-economic-assumptions/2026/e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9/prefu26-charts-data.xlsx", + "source_file": "prefu26-charts-data.xlsx", + "source_name": "treasury", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_size_bytes": 664670, + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts", + "url": "https://www.treasury.govt.nz/sites/default/files/2026-09/prefu26-charts-data.xlsx", + "vintage": "prefu_2026_09_29" + }, + "unit": "percent", + "assertion": "source_projection", + "provenance_class": "model_output", + "entity_role": "forecaster", + "period_coverage": { + "basis": "fiscal", + "end_date": "2027-06-30", + "notes": "Publisher Year ending 30 June 2027; Chronicle opening-year fiscal_year:2026. Publisher column status is Forecast. Footnote 3 (Table 4.1!C21:D21): Ordinary time. Footnote 4 (C22:D22): Measures are actuals except for real GDP and nominal GDP. 2026 earnings are therefore actuals despite the Forecast4 column heading; only 2027–2031 earnings are forecasts. The published annual percentage change is retained unchanged; no annual average, level, factor or period alignment is calculated.", + "source_period_label": "Year ending 30 June 2027", + "start_date": "2026-07-01" + }, + "unit_multiplier": "0.01", + "scenario_delta": "-0.5", + "sensitivity_provenance": [ + "d1599: symmetric ±0.5 percentage-point Microcosm sensitivity; high is not a Treasury forecast path" + ], + "effective_growth": { + "numerator": 11, + "denominator": 500 + } + }, + "root_bounds": { + "lower": { + "numerator": 50272759932393, + "denominator": 50000000000000 + }, + "upper": { + "numerator": 100545519864787, + "denominator": 100000000000000 + }, + "exact": false, + "decimal_places": 14, + "degree": 4, + "radicand": { + "numerator": 511, + "denominator": 500 + } + }, + "numerator_mean_bounds": { + "lower": { + "numerator": 21433087509261019469100089110351817978329164269, + "denominator": 12500000000000000000000000000000000000000000 + }, + "upper": { + "numerator": 171464700074090725365853333139754513013059781351, + "denominator": 100000000000000000000000000000000000000000000 + } + }, + "unrounded_factor_bounds": { + "lower": { + "numerator": 21433087509261019469100089110351817978329164269, + "denominator": 20875906250000000000000000000000000000000000000 + }, + "upper": { + "numerator": 171464700074090725365853333139754513013059781351, + "denominator": 167007250000000000000000000000000000000000000000 + } + }, + "rounding": { + "digits": 6, + "mode": "nearest_half_even" + }, + "operational_factor": { + "numerator": 1026690, + "denominator": 1000000 + }, + "validity": { + "declared_on": "2026-10-23", + "valid_from": "2026-10-23", + "valid_until": "2026-11-03", + "as_of": "2026-10-23" + }, + "evidence": [ + "Stats NZ QES Table 7; QEMQ.SBSZ9A; ordinary-time FTE, all sectors, actual", + "Treasury PREFU 2026 Table 4.1; year ending 30 June 2027; Chronicle period 2026" + ], + "decision_references": [ + "d1599; IRD band ageing factors, 22 October 2026", + "G8-r2 hub rulings 3, 23 October 2026, sections 1–2" + ], + "receipt_sha256": "28006b689061f41a7cfd9abf055aa3ee1ee5a5414d83fa255d36d5ee7fe326bc" + } + }, + { + "declaration": { + "schema_version": 1, + "id": "p1_ty2026_to_ty2027_central", + "operation": "projected_period_average_ratio", + "operation_version": 1, + "purpose": "profile_input", + "feed_identity": { + "source_commit": "8f4cfd573c0d6f580d9c51cd67e8f449a42ed174", + "facts_sha256": "03f5ea0fe60e6dc93a135ab32cd5cd6ffb56388e702a4734cdb515a956e36b18", + "manifest_sha256": "1ea2d1eeb122275a9ce7f861ca3e20e21dd695772c04ce9d71114168e92fe053", + "artifact_schema_version": "policyengine_ledger.consumer_artifact.v2", + "consumer_fact_schema_versions": [ + "chronicle.consumer_fact.v4" + ], + "consumer_fact_schema_sha256": "d953306d6f01fbc64db4372d0262d3012ee590269f8a25b276b18dca0626c6a0", + "fact_row_count": 12368 + }, + "source_period": 2026, + "target_period": 2027, + "source_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:86ce22ba42a6e2a36b889f9b", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-04-01", + "end_date": "2025-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:434e7b2736b4b16589034c72", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-07-01", + "end_date": "2025-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:bc87e53157eaf53c846879dc", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-10-01", + "end_date": "2025-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:78e735569814069f8066ba9f", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-01-01", + "end_date": "2026-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 3 + } + ], + "target_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-04-01", + "end_date": "2026-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 0, + "projection_offset": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2026-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 1, + "projection_offset": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-10-01", + "end_date": "2026-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 2, + "projection_offset": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2027-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2027q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2027-01-01", + "end_date": "2027-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 3, + "projection_offset": 3 + } + ], + "growth": { + "selector": { + "source_name": "treasury", + "source_measure_id": "average_weekly_earnings_annual_percentage_change", + "source_concept": "treasury.prefu26.average_weekly_earnings_annual_percentage_change", + "entity_name": "government", + "period_type": "fiscal_year", + "period_value": 2026, + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "treasury.prefu26.average_weekly_earnings.fy2026", + "dimensions": [ + "earnings_component", + "publication_status" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "publication_status": "Forecast" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "assertion": "source_projection", + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts" + }, + "validation": { + "unit": "percent", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_vintage": "prefu_2026_09_29", + "entity_role": "forecaster", + "provenance_class": "model_output", + "assertion": "source_projection", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2027-06-30" + }, + "source_column_id": "year_ending_30_june_2027" + }, + "unit_multiplier": "0.01", + "scenario_delta": "0", + "assertion_policy": "allow_source_projection", + "sensitivity_provenance": [ + "d1599: symmetric ±0.5 percentage-point Microcosm sensitivity; high is not a Treasury forecast path" + ] + }, + "subperiods_per_year": 4, + "projection_policy": "observed_preferred_latest_contiguous", + "rounding": { + "digits": 6, + "mode": "nearest_half_even" + }, + "expected_operational_factor": { + "numerator": 1028580, + "denominator": 1000000 + }, + "validity": { + "declared_on": "2026-10-23", + "valid_from": "2026-10-23", + "valid_until": "2026-11-03", + "as_of": "2026-10-23" + }, + "evidence": [ + "Stats NZ QES Table 7; QEMQ.SBSZ9A; ordinary-time FTE, all sectors, actual", + "Treasury PREFU 2026 Table 4.1; year ending 30 June 2027; Chronicle period 2026" + ], + "decision_references": [ + "d1599; IRD band ageing factors, 22 October 2026", + "G8-r2 hub rulings 3, 23 October 2026, sections 1–2" + ] + }, + "operational_factor": { + "numerator": 1028580, + "denominator": 1000000 + }, + "receipt": { + "schema_version": 1, + "operation": "projected_period_average_ratio", + "operation_version": 1, + "factor_id": "p1_ty2026_to_ty2027_central", + "declaration_sha256": "8507fe3d665c6a0727319765827120afda4ee36e8d970a70b61a747d8cb9210b", + "feed_identity": { + "source_commit": "8f4cfd573c0d6f580d9c51cd67e8f449a42ed174", + "facts_sha256": "03f5ea0fe60e6dc93a135ab32cd5cd6ffb56388e702a4734cdb515a956e36b18", + "manifest_sha256": "1ea2d1eeb122275a9ce7f861ca3e20e21dd695772c04ce9d71114168e92fe053", + "artifact_schema_version": "policyengine_ledger.consumer_artifact.v2", + "consumer_fact_schema_versions": [ + "chronicle.consumer_fact.v4" + ], + "consumer_fact_schema_sha256": "d953306d6f01fbc64db4372d0262d3012ee590269f8a25b276b18dca0626c6a0", + "fact_row_count": 12368 + }, + "source_period": 2026, + "target_period": 2027, + "source_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:86ce22ba42a6e2a36b889f9b", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:86ce22ba42a6e2a36b889f9b", + "decimal_operand": "1652.72", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1652.72", + "recovered_decimal": "1652.72", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-04-01", + "end_date": "2025-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2025-Q2" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2025-06-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Jun 2025 quarter", + "start_date": "2025-04-01" + }, + "weight": "1", + "sequence": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:434e7b2736b4b16589034c72", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:434e7b2736b4b16589034c72", + "decimal_operand": "1661.12", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1661.12", + "recovered_decimal": "1661.12", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-07-01", + "end_date": "2025-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2025-Q3" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2025-09-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Sep 2025 quarter", + "start_date": "2025-07-01" + }, + "weight": "1", + "sequence": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:bc87e53157eaf53c846879dc", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:bc87e53157eaf53c846879dc", + "decimal_operand": "1681.06", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1681.06", + "recovered_decimal": "1681.06", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-10-01", + "end_date": "2025-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2025-Q4" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2025-12-31", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Dec 2025 quarter", + "start_date": "2025-10-01" + }, + "weight": "1", + "sequence": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:78e735569814069f8066ba9f", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:78e735569814069f8066ba9f", + "decimal_operand": "1685.39", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1685.39", + "recovered_decimal": "1685.39", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-01-01", + "end_date": "2026-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2026-Q1" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2026-03-31", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Mar 2026 quarter", + "start_date": "2026-01-01" + }, + "weight": "1", + "sequence": 3 + } + ], + "target_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "decimal_operand": "1700.68", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1700.68", + "recovered_decimal": "1700.68", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-04-01", + "end_date": "2026-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2026-Q2" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2026-06-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Jun 2026 quarter", + "start_date": "2026-04-01" + }, + "status": "observed", + "sequence": 0, + "weight": "1", + "projection_offset": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2026-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 1, + "weight": "1", + "projection_offset": 1, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-10-01", + "end_date": "2026-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 2, + "weight": "1", + "projection_offset": 2, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2027-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2027q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2027-01-01", + "end_date": "2027-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 3, + "weight": "1", + "projection_offset": 3, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + } + ], + "subperiods_per_year": 4, + "projection_policy": "observed_preferred_latest_contiguous", + "denominator_mean": { + "numerator": 668029, + "denominator": 400 + }, + "growth": { + "selector": { + "source_name": "treasury", + "source_measure_id": "average_weekly_earnings_annual_percentage_change", + "source_concept": "treasury.prefu26.average_weekly_earnings_annual_percentage_change", + "entity_name": "government", + "period_type": "fiscal_year", + "period_value": 2026, + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "treasury.prefu26.average_weekly_earnings.fy2026", + "dimensions": [ + "earnings_component", + "publication_status" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "publication_status": "Forecast" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "assertion": "source_projection", + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "decimal_operand": "2.7", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "2.7", + "recovered_decimal": "2.7", + "decimal_values_equal": true + }, + "validation": { + "unit": "percent", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_vintage": "prefu_2026_09_29", + "entity_role": "forecaster", + "provenance_class": "model_output", + "assertion": "source_projection", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2027-06-30" + }, + "source_column_id": "year_ending_30_june_2027" + }, + "period": { + "type": "fiscal_year", + "value": 2026 + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/treasury/treasury-prefu26-economic-assumptions/2026/e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9/prefu26-charts-data.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/treasury/treasury-prefu26-economic-assumptions/2026/e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9/prefu26-charts-data.xlsx", + "source_file": "prefu26-charts-data.xlsx", + "source_name": "treasury", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_size_bytes": 664670, + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts", + "url": "https://www.treasury.govt.nz/sites/default/files/2026-09/prefu26-charts-data.xlsx", + "vintage": "prefu_2026_09_29" + }, + "unit": "percent", + "assertion": "source_projection", + "provenance_class": "model_output", + "entity_role": "forecaster", + "period_coverage": { + "basis": "fiscal", + "end_date": "2027-06-30", + "notes": "Publisher Year ending 30 June 2027; Chronicle opening-year fiscal_year:2026. Publisher column status is Forecast. Footnote 3 (Table 4.1!C21:D21): Ordinary time. Footnote 4 (C22:D22): Measures are actuals except for real GDP and nominal GDP. 2026 earnings are therefore actuals despite the Forecast4 column heading; only 2027–2031 earnings are forecasts. The published annual percentage change is retained unchanged; no annual average, level, factor or period alignment is calculated.", + "source_period_label": "Year ending 30 June 2027", + "start_date": "2026-07-01" + }, + "unit_multiplier": "0.01", + "scenario_delta": "0", + "sensitivity_provenance": [ + "d1599: symmetric ±0.5 percentage-point Microcosm sensitivity; high is not a Treasury forecast path" + ], + "effective_growth": { + "numerator": 27, + "denominator": 1000 + } + }, + "root_bounds": { + "lower": { + "numerator": 100668271307927, + "denominator": 100000000000000 + }, + "upper": { + "numerator": 12583533913491, + "denominator": 12500000000000 + }, + "exact": false, + "decimal_places": 14, + "degree": 4, + "radicand": { + "numerator": 1027, + "denominator": 1000 + } + }, + "numerator_mean_bounds": { + "lower": { + "numerator": 171780381168748188591006079321988113950935096211, + "denominator": 100000000000000000000000000000000000000000000 + }, + "upper": { + "numerator": 335508556970216332809143747140199880884173607, + "denominator": 195312500000000000000000000000000000000000 + } + }, + "unrounded_factor_bounds": { + "lower": { + "numerator": 171780381168748188591006079321988113950935096211, + "denominator": 167007250000000000000000000000000000000000000000 + }, + "upper": { + "numerator": 335508556970216332809143747140199880884173607, + "denominator": 326186035156250000000000000000000000000000000 + } + }, + "rounding": { + "digits": 6, + "mode": "nearest_half_even" + }, + "operational_factor": { + "numerator": 1028580, + "denominator": 1000000 + }, + "validity": { + "declared_on": "2026-10-23", + "valid_from": "2026-10-23", + "valid_until": "2026-11-03", + "as_of": "2026-10-23" + }, + "evidence": [ + "Stats NZ QES Table 7; QEMQ.SBSZ9A; ordinary-time FTE, all sectors, actual", + "Treasury PREFU 2026 Table 4.1; year ending 30 June 2027; Chronicle period 2026" + ], + "decision_references": [ + "d1599; IRD band ageing factors, 22 October 2026", + "G8-r2 hub rulings 3, 23 October 2026, sections 1–2" + ], + "receipt_sha256": "43e1914b11969709ea4f0df7fc9a8280f82f15bf186b4e107f986da0a7871c53" + } + }, + { + "declaration": { + "schema_version": 1, + "id": "p1_ty2026_to_ty2027_high", + "operation": "projected_period_average_ratio", + "operation_version": 1, + "purpose": "profile_input", + "feed_identity": { + "source_commit": "8f4cfd573c0d6f580d9c51cd67e8f449a42ed174", + "facts_sha256": "03f5ea0fe60e6dc93a135ab32cd5cd6ffb56388e702a4734cdb515a956e36b18", + "manifest_sha256": "1ea2d1eeb122275a9ce7f861ca3e20e21dd695772c04ce9d71114168e92fe053", + "artifact_schema_version": "policyengine_ledger.consumer_artifact.v2", + "consumer_fact_schema_versions": [ + "chronicle.consumer_fact.v4" + ], + "consumer_fact_schema_sha256": "d953306d6f01fbc64db4372d0262d3012ee590269f8a25b276b18dca0626c6a0", + "fact_row_count": 12368 + }, + "source_period": 2026, + "target_period": 2027, + "source_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:86ce22ba42a6e2a36b889f9b", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-04-01", + "end_date": "2025-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:434e7b2736b4b16589034c72", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-07-01", + "end_date": "2025-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:bc87e53157eaf53c846879dc", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-10-01", + "end_date": "2025-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:78e735569814069f8066ba9f", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-01-01", + "end_date": "2026-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 3 + } + ], + "target_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-04-01", + "end_date": "2026-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 0, + "projection_offset": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2026-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 1, + "projection_offset": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-10-01", + "end_date": "2026-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 2, + "projection_offset": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2027-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2027q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2027-01-01", + "end_date": "2027-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 3, + "projection_offset": 3 + } + ], + "growth": { + "selector": { + "source_name": "treasury", + "source_measure_id": "average_weekly_earnings_annual_percentage_change", + "source_concept": "treasury.prefu26.average_weekly_earnings_annual_percentage_change", + "entity_name": "government", + "period_type": "fiscal_year", + "period_value": 2026, + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "treasury.prefu26.average_weekly_earnings.fy2026", + "dimensions": [ + "earnings_component", + "publication_status" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "publication_status": "Forecast" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "assertion": "source_projection", + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts" + }, + "validation": { + "unit": "percent", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_vintage": "prefu_2026_09_29", + "entity_role": "forecaster", + "provenance_class": "model_output", + "assertion": "source_projection", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2027-06-30" + }, + "source_column_id": "year_ending_30_june_2027" + }, + "unit_multiplier": "0.01", + "scenario_delta": "0.5", + "assertion_policy": "allow_source_projection", + "sensitivity_provenance": [ + "d1599: symmetric ±0.5 percentage-point Microcosm sensitivity; high is not a Treasury forecast path" + ] + }, + "subperiods_per_year": 4, + "projection_policy": "observed_preferred_latest_contiguous", + "rounding": { + "digits": 6, + "mode": "nearest_half_even" + }, + "expected_operational_factor": { + "numerator": 1030467, + "denominator": 1000000 + }, + "validity": { + "declared_on": "2026-10-23", + "valid_from": "2026-10-23", + "valid_until": "2026-11-03", + "as_of": "2026-10-23" + }, + "evidence": [ + "Stats NZ QES Table 7; QEMQ.SBSZ9A; ordinary-time FTE, all sectors, actual", + "Treasury PREFU 2026 Table 4.1; year ending 30 June 2027; Chronicle period 2026" + ], + "decision_references": [ + "d1599; IRD band ageing factors, 22 October 2026", + "G8-r2 hub rulings 3, 23 October 2026, sections 1–2" + ] + }, + "operational_factor": { + "numerator": 1030467, + "denominator": 1000000 + }, + "receipt": { + "schema_version": 1, + "operation": "projected_period_average_ratio", + "operation_version": 1, + "factor_id": "p1_ty2026_to_ty2027_high", + "declaration_sha256": "b2c2c0b631861fa6c3975dfb6d326b49ca60b81057abc5bb8581dd0c0bca1ce9", + "feed_identity": { + "source_commit": "8f4cfd573c0d6f580d9c51cd67e8f449a42ed174", + "facts_sha256": "03f5ea0fe60e6dc93a135ab32cd5cd6ffb56388e702a4734cdb515a956e36b18", + "manifest_sha256": "1ea2d1eeb122275a9ce7f861ca3e20e21dd695772c04ce9d71114168e92fe053", + "artifact_schema_version": "policyengine_ledger.consumer_artifact.v2", + "consumer_fact_schema_versions": [ + "chronicle.consumer_fact.v4" + ], + "consumer_fact_schema_sha256": "d953306d6f01fbc64db4372d0262d3012ee590269f8a25b276b18dca0626c6a0", + "fact_row_count": 12368 + }, + "source_period": 2026, + "target_period": 2027, + "source_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:86ce22ba42a6e2a36b889f9b", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:86ce22ba42a6e2a36b889f9b", + "decimal_operand": "1652.72", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1652.72", + "recovered_decimal": "1652.72", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-04-01", + "end_date": "2025-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2025-Q2" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2025-06-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Jun 2025 quarter", + "start_date": "2025-04-01" + }, + "weight": "1", + "sequence": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:434e7b2736b4b16589034c72", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:434e7b2736b4b16589034c72", + "decimal_operand": "1661.12", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1661.12", + "recovered_decimal": "1661.12", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-07-01", + "end_date": "2025-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2025-Q3" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2025-09-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Sep 2025 quarter", + "start_date": "2025-07-01" + }, + "weight": "1", + "sequence": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:bc87e53157eaf53c846879dc", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:bc87e53157eaf53c846879dc", + "decimal_operand": "1681.06", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1681.06", + "recovered_decimal": "1681.06", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-10-01", + "end_date": "2025-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2025-Q4" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2025-12-31", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Dec 2025 quarter", + "start_date": "2025-10-01" + }, + "weight": "1", + "sequence": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:78e735569814069f8066ba9f", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:78e735569814069f8066ba9f", + "decimal_operand": "1685.39", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1685.39", + "recovered_decimal": "1685.39", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-01-01", + "end_date": "2026-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2026-Q1" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2026-03-31", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Mar 2026 quarter", + "start_date": "2026-01-01" + }, + "weight": "1", + "sequence": 3 + } + ], + "target_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2", + "decimal_operand": "1700.68", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1700.68", + "recovered_decimal": "1700.68", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-04-01", + "end_date": "2026-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2026-Q2" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2026-06-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Jun 2026 quarter", + "start_date": "2026-04-01" + }, + "status": "observed", + "sequence": 0, + "weight": "1", + "projection_offset": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2026-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 1, + "weight": "1", + "projection_offset": 1, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-10-01", + "end_date": "2026-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 2, + "weight": "1", + "projection_offset": 2, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2027-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2027q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2027-01-01", + "end_date": "2027-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "status": "projected", + "sequence": 3, + "weight": "1", + "projection_offset": 3, + "projection_anchor": { + "aggregate_fact_key": "ledger.aggregate_fact.v2:91583e3f39d11b8b4b2923d2" + } + } + ], + "subperiods_per_year": 4, + "projection_policy": "observed_preferred_latest_contiguous", + "denominator_mean": { + "numerator": 668029, + "denominator": 400 + }, + "growth": { + "selector": { + "source_name": "treasury", + "source_measure_id": "average_weekly_earnings_annual_percentage_change", + "source_concept": "treasury.prefu26.average_weekly_earnings_annual_percentage_change", + "entity_name": "government", + "period_type": "fiscal_year", + "period_value": 2026, + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "treasury.prefu26.average_weekly_earnings.fy2026", + "dimensions": [ + "earnings_component", + "publication_status" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "publication_status": "Forecast" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "assertion": "source_projection", + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25", + "decimal_operand": "2.7", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "2.7", + "recovered_decimal": "2.7", + "decimal_values_equal": true + }, + "validation": { + "unit": "percent", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_vintage": "prefu_2026_09_29", + "entity_role": "forecaster", + "provenance_class": "model_output", + "assertion": "source_projection", + "period_coverage": { + "start_date": "2026-07-01", + "end_date": "2027-06-30" + }, + "source_column_id": "year_ending_30_june_2027" + }, + "period": { + "type": "fiscal_year", + "value": 2026 + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/treasury/treasury-prefu26-economic-assumptions/2026/e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9/prefu26-charts-data.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/treasury/treasury-prefu26-economic-assumptions/2026/e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9/prefu26-charts-data.xlsx", + "source_file": "prefu26-charts-data.xlsx", + "source_name": "treasury", + "source_sha256": "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9", + "source_size_bytes": 664670, + "source_table": "PREFU 2026 Table 4.1 - Key economic assumptions for fiscal forecasts", + "url": "https://www.treasury.govt.nz/sites/default/files/2026-09/prefu26-charts-data.xlsx", + "vintage": "prefu_2026_09_29" + }, + "unit": "percent", + "assertion": "source_projection", + "provenance_class": "model_output", + "entity_role": "forecaster", + "period_coverage": { + "basis": "fiscal", + "end_date": "2027-06-30", + "notes": "Publisher Year ending 30 June 2027; Chronicle opening-year fiscal_year:2026. Publisher column status is Forecast. Footnote 3 (Table 4.1!C21:D21): Ordinary time. Footnote 4 (C22:D22): Measures are actuals except for real GDP and nominal GDP. 2026 earnings are therefore actuals despite the Forecast4 column heading; only 2027–2031 earnings are forecasts. The published annual percentage change is retained unchanged; no annual average, level, factor or period alignment is calculated.", + "source_period_label": "Year ending 30 June 2027", + "start_date": "2026-07-01" + }, + "unit_multiplier": "0.01", + "scenario_delta": "0.5", + "sensitivity_provenance": [ + "d1599: symmetric ±0.5 percentage-point Microcosm sensitivity; high is not a Treasury forecast path" + ], + "effective_growth": { + "numerator": 4, + "denominator": 125 + } + }, + "root_bounds": { + "lower": { + "numerator": 100790575349881, + "denominator": 100000000000000 + }, + "upper": { + "numerator": 50395287674941, + "denominator": 50000000000000 + }, + "exact": false, + "decimal_places": 14, + "degree": 4, + "radicand": { + "numerator": 129, + "denominator": 125 + } + }, + "numerator_mean_bounds": { + "lower": { + "numerator": 172095423947015521933465483088234150187075944797, + "denominator": 100000000000000000000000000000000000000000000 + }, + "upper": { + "numerator": 21511927993377262490437471966978882670435826057, + "denominator": 12500000000000000000000000000000000000000000 + } + }, + "unrounded_factor_bounds": { + "lower": { + "numerator": 172095423947015521933465483088234150187075944797, + "denominator": 167007250000000000000000000000000000000000000000 + }, + "upper": { + "numerator": 21511927993377262490437471966978882670435826057, + "denominator": 20875906250000000000000000000000000000000000000 + } + }, + "rounding": { + "digits": 6, + "mode": "nearest_half_even" + }, + "operational_factor": { + "numerator": 1030467, + "denominator": 1000000 + }, + "validity": { + "declared_on": "2026-10-23", + "valid_from": "2026-10-23", + "valid_until": "2026-11-03", + "as_of": "2026-10-23" + }, + "evidence": [ + "Stats NZ QES Table 7; QEMQ.SBSZ9A; ordinary-time FTE, all sectors, actual", + "Treasury PREFU 2026 Table 4.1; year ending 30 June 2027; Chronicle period 2026" + ], + "decision_references": [ + "d1599; IRD band ageing factors, 22 October 2026", + "G8-r2 hub rulings 3, 23 October 2026, sections 1–2" + ], + "receipt_sha256": "5d1b1006938c2628d7f2d4344643270c2477f01cd0d313bfa323834ff8e54cb2" + } + }, + { + "declaration": { + "schema_version": 1, + "id": "observed_ty2026_over_ty2024", + "operation": "projected_period_average_ratio", + "operation_version": 1, + "purpose": "diagnostic", + "feed_identity": { + "source_commit": "8f4cfd573c0d6f580d9c51cd67e8f449a42ed174", + "facts_sha256": "03f5ea0fe60e6dc93a135ab32cd5cd6ffb56388e702a4734cdb515a956e36b18", + "manifest_sha256": "1ea2d1eeb122275a9ce7f861ca3e20e21dd695772c04ce9d71114168e92fe053", + "artifact_schema_version": "policyengine_ledger.consumer_artifact.v2", + "consumer_fact_schema_versions": [ + "chronicle.consumer_fact.v4" + ], + "consumer_fact_schema_sha256": "d953306d6f01fbc64db4372d0262d3012ee590269f8a25b276b18dca0626c6a0", + "fact_row_count": 12368 + }, + "source_period": 2024, + "target_period": 2026, + "source_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:cfbce1343aa646fce0411631", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-04-01", + "end_date": "2023-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:f9f4f127d080fe2f06617947", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-07-01", + "end_date": "2023-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:fb5938810b7b37ae8534e5f7", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-10-01", + "end_date": "2023-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2024-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2024q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:854e91ec1dd95e396659ad8e", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2024-01-01", + "end_date": "2024-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 3 + } + ], + "target_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:86ce22ba42a6e2a36b889f9b", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-04-01", + "end_date": "2025-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 0, + "projection_offset": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:434e7b2736b4b16589034c72", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-07-01", + "end_date": "2025-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 1, + "projection_offset": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:bc87e53157eaf53c846879dc", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-10-01", + "end_date": "2025-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 2, + "projection_offset": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:78e735569814069f8066ba9f", + "assertion": "observation" + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-01-01", + "end_date": "2026-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "weight": "1", + "sequence": 3, + "projection_offset": 3 + } + ], + "growth": null, + "subperiods_per_year": 4, + "projection_policy": "observed_preferred_latest_contiguous", + "rounding": { + "digits": 6, + "mode": "nearest_half_even" + }, + "expected_operational_factor": { + "numerator": 1086069, + "denominator": 1000000 + }, + "validity": { + "declared_on": "2026-10-23", + "valid_from": "2026-10-23", + "valid_until": "2026-11-03", + "as_of": "2026-10-23" + }, + "evidence": [ + "Stats NZ QES Table 7; QEMQ.SBSZ9A; ordinary-time FTE, all sectors, actual", + "Treasury PREFU 2026 Table 4.1; year ending 30 June 2027; Chronicle period 2026" + ], + "decision_references": [ + "d1599; IRD band ageing factors, 22 October 2026", + "G8-r2 hub rulings 3, 23 October 2026, sections 1–2" + ] + }, + "operational_factor": { + "numerator": 1086069, + "denominator": 1000000 + }, + "receipt": { + "schema_version": 1, + "operation": "projected_period_average_ratio", + "operation_version": 1, + "factor_id": "observed_ty2026_over_ty2024", + "declaration_sha256": "dae0d44f673fb8e437c4787b3c0d6d6c142412c2fbb29e03f1702a6940a56316", + "feed_identity": { + "source_commit": "8f4cfd573c0d6f580d9c51cd67e8f449a42ed174", + "facts_sha256": "03f5ea0fe60e6dc93a135ab32cd5cd6ffb56388e702a4734cdb515a956e36b18", + "manifest_sha256": "1ea2d1eeb122275a9ce7f861ca3e20e21dd695772c04ce9d71114168e92fe053", + "artifact_schema_version": "policyengine_ledger.consumer_artifact.v2", + "consumer_fact_schema_versions": [ + "chronicle.consumer_fact.v4" + ], + "consumer_fact_schema_sha256": "d953306d6f01fbc64db4372d0262d3012ee590269f8a25b276b18dca0626c6a0", + "fact_row_count": 12368 + }, + "source_period": 2024, + "target_period": 2026, + "source_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:cfbce1343aa646fce0411631", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:cfbce1343aa646fce0411631", + "decimal_operand": "1502.27", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1502.27", + "recovered_decimal": "1502.27", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-04-01", + "end_date": "2023-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2023-Q2" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2025-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_size_bytes": 135784, + "source_table": "Quarterly Employment Survey June 2025 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2025-quarter/Download-data/quarterly-employment-survey-june-2025-quarter.xlsx", + "vintage": "stats_nz_qes_june_2025" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2023-06-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Jun 2023 quarter", + "start_date": "2023-04-01" + }, + "weight": "1", + "sequence": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:f9f4f127d080fe2f06617947", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:f9f4f127d080fe2f06617947", + "decimal_operand": "1528.92", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1528.92", + "recovered_decimal": "1528.92", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-07-01", + "end_date": "2023-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2023-Q3" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2025-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_size_bytes": 135784, + "source_table": "Quarterly Employment Survey June 2025 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2025-quarter/Download-data/quarterly-employment-survey-june-2025-quarter.xlsx", + "vintage": "stats_nz_qes_june_2025" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2023-09-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Sep 2023 quarter", + "start_date": "2023-07-01" + }, + "weight": "1", + "sequence": 1 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2023-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2023q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:fb5938810b7b37ae8534e5f7", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:fb5938810b7b37ae8534e5f7", + "decimal_operand": "1556.16", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1556.16", + "recovered_decimal": "1556.16", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2023-10-01", + "end_date": "2023-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2023-Q4" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2025-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_size_bytes": 135784, + "source_table": "Quarterly Employment Survey June 2025 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2025-quarter/Download-data/quarterly-employment-survey-june-2025-quarter.xlsx", + "vintage": "stats_nz_qes_june_2025" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2023-12-31", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Dec 2023 quarter", + "start_date": "2023-10-01" + }, + "weight": "1", + "sequence": 2 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2024-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2024q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:854e91ec1dd95e396659ad8e", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:854e91ec1dd95e396659ad8e", + "decimal_operand": "1563.54", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1563.54", + "recovered_decimal": "1563.54", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_vintage": "stats_nz_qes_june_2025", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2024-01-01", + "end_date": "2024-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2024-Q1" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2025/2025/25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30/quarterly-employment-survey-june-2025-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2025-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30", + "source_size_bytes": 135784, + "source_table": "Quarterly Employment Survey June 2025 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2025-quarter/Download-data/quarterly-employment-survey-june-2025-quarter.xlsx", + "vintage": "stats_nz_qes_june_2025" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2024-03-31", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Mar 2024 quarter", + "start_date": "2024-01-01" + }, + "weight": "1", + "sequence": 3 + } + ], + "target_schedule": [ + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q2", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q2", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:86ce22ba42a6e2a36b889f9b", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:86ce22ba42a6e2a36b889f9b", + "decimal_operand": "1652.72", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1652.72", + "recovered_decimal": "1652.72", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-04-01", + "end_date": "2025-06-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2025-Q2" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2025-06-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Jun 2025 quarter", + "start_date": "2025-04-01" + }, + "status": "observed", + "sequence": 0, + "weight": "1", + "projection_offset": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q3", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q3", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:434e7b2736b4b16589034c72", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:434e7b2736b4b16589034c72", + "decimal_operand": "1661.12", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1661.12", + "recovered_decimal": "1661.12", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-07-01", + "end_date": "2025-09-30" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2025-Q3" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2025-09-30", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Sep 2025 quarter", + "start_date": "2025-07-01" + }, + "status": "observed", + "sequence": 1, + "weight": "1", + "projection_offset": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2025-Q4", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2025q4", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:bc87e53157eaf53c846879dc", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:bc87e53157eaf53c846879dc", + "decimal_operand": "1681.06", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1681.06", + "recovered_decimal": "1681.06", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2025-10-01", + "end_date": "2025-12-31" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2025-Q4" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2025-12-31", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Dec 2025 quarter", + "start_date": "2025-10-01" + }, + "status": "observed", + "sequence": 2, + "weight": "1", + "projection_offset": 0 + }, + { + "selector": { + "source_name": "stats_nz", + "source_measure_id": "SBSZ9A", + "source_concept": "stats_nz.qes.average_weekly_earnings.ordinary_time", + "entity_name": "person", + "period_type": "quarter", + "period_value": "2026-Q1", + "geography_level": "country", + "geography_id": "NZ", + "geography_vintage": "current", + "record_set_id": "stats_nz.qes.awe.2026q1", + "dimensions": [ + "earnings_component", + "earnings_denominator", + "earnings_sector", + "earnings_series_reference", + "seasonal_adjustment" + ], + "dimension_values": { + "earnings_component": "ordinary_time", + "earnings_denominator": "fte", + "earnings_sector": "all_sectors", + "earnings_series_reference": "QEMQ.SBSZ9A", + "seasonal_adjustment": "actual" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:78e735569814069f8066ba9f", + "assertion": "observation" + }, + "aggregate_fact_key": "ledger.aggregate_fact.v2:78e735569814069f8066ba9f", + "decimal_operand": "1685.39", + "numeric_token_proof": { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "1685.39", + "recovered_decimal": "1685.39", + "decimal_values_equal": true + }, + "validation": { + "unit": "nzd_per_week", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_vintage": "stats_nz_qes_june_2026", + "entity_role": "full_time_equivalent_employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + "period_coverage": { + "start_date": "2026-01-01", + "end_date": "2026-03-31" + }, + "source_column_id": "SBSZ9A" + }, + "period": { + "type": "quarter", + "value": "2026-Q1" + }, + "source": { + "extracted_at": "2026-10-22", + "extraction_method": "CellSelectorSpec and SourceRecordSpec resolved from cells", + "method_notes": "Each fact carries source_record_id, source_cell_keys, and source_row_keys when available.", + "raw_r2_bucket": "ledger-raw", + "raw_r2_key": "raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "raw_r2_uri": "r2://ledger-raw/raw/nz/stats_nz/qes_average_weekly_earnings_june_2026/2026/1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97/quarterly-employment-survey-june-2026-quarter.xlsx", + "source_file": "quarterly-employment-survey-june-2026-quarter.xlsx", + "source_name": "stats_nz", + "source_sha256": "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97", + "source_size_bytes": 124556, + "source_table": "Quarterly Employment Survey June 2026 quarter, Table 7: Average weekly earnings for FTEs, by sector", + "url": "https://www.stats.govt.nz/assets/Uploads/Labour-market-statistics/Labour-market-statistics-June-2026-quarter/Download-data/quarterly-employment-survey-june-2026-quarter.xlsx", + "vintage": "stats_nz_qes_june_2026" + }, + "unit": "nzd_per_week", + "assertion": "observation", + "provenance_class": "survey_aggregate", + "entity_role": "full_time_equivalent_employee", + "period_coverage": { + "basis": "calendar", + "end_date": "2026-03-31", + "notes": "QES reference period is the pay week ending on or before the 20th of the quarter’s middle month (hub-supplied source-period definition); the fact period is the published quarter, not the pay week. Actual, not seasonally adjusted. No annual averaging or period alignment.", + "source_period_label": "Mar 2026 quarter", + "start_date": "2026-01-01" + }, + "status": "observed", + "sequence": 3, + "weight": "1", + "projection_offset": 0 + } + ], + "subperiods_per_year": 4, + "projection_policy": "observed_preferred_latest_contiguous", + "denominator_mean": { + "numerator": 615089, + "denominator": 400 + }, + "growth": null, + "root_bounds": { + "lower": { + "numerator": 1, + "denominator": 1 + }, + "upper": { + "numerator": 1, + "denominator": 1 + }, + "exact": true, + "decimal_places": 14, + "degree": 4, + "radicand": { + "numerator": 1, + "denominator": 1 + } + }, + "numerator_mean_bounds": { + "lower": { + "numerator": 668029, + "denominator": 400 + }, + "upper": { + "numerator": 668029, + "denominator": 400 + } + }, + "unrounded_factor_bounds": { + "lower": { + "numerator": 668029, + "denominator": 615089 + }, + "upper": { + "numerator": 668029, + "denominator": 615089 + } + }, + "rounding": { + "digits": 6, + "mode": "nearest_half_even" + }, + "operational_factor": { + "numerator": 1086069, + "denominator": 1000000 + }, + "validity": { + "declared_on": "2026-10-23", + "valid_from": "2026-10-23", + "valid_until": "2026-11-03", + "as_of": "2026-10-23" + }, + "evidence": [ + "Stats NZ QES Table 7; QEMQ.SBSZ9A; ordinary-time FTE, all sectors, actual", + "Treasury PREFU 2026 Table 4.1; year ending 30 June 2027; Chronicle period 2026" + ], + "decision_references": [ + "d1599; IRD band ageing factors, 22 October 2026", + "G8-r2 hub rulings 3, 23 October 2026, sections 1–2" + ], + "receipt_sha256": "6487bd1664ce1e691faaa0771e9835da5437243b06a5c7d749888380a76cd995" + } + } + ] +} diff --git a/packages/microcosm-build/src/microcosm/build/nz/reference_intervals.json b/packages/microcosm-build/src/microcosm/build/nz/reference_intervals.json new file mode 100644 index 0000000000..991a9b4984 --- /dev/null +++ b/packages/microcosm-build/src/microcosm/build/nz/reference_intervals.json @@ -0,0 +1,3464 @@ +{ + "schema_version": 1, + "country": "nz", + "description": "Generated by tools/generate_nz_target_references.py from the row formulas and checked against the pinned feed's own band labels.", + "disclosure": "IRD publishes no band closure or cents semantics for these tables. The cuts, closure, nil band and integer-cent arithmetic are Microcosm's declared convention (G8-r open rulings 2, section 1, 23 October 2026), not IRD's own semantics: t = max(0, x) in integer cents with no dollar rounding; t == 0 is the nil band, including qualifying loss records; each positive band is previous_upper < t <= upper; and the open tail is t > its lower cut. Four published label pairs share an endpoint ($20,000, $50,000, $80,000 and $300,000: national rows 29/30, 59/60, 89/90 and 229/230; age rows 27/28, 57/58 and 87/88); the ordered right-closed cuts assign each shared endpoint to the lower band. Ageing scales every finite cut exactly by the selected factor and keeps fractional cents. The income and universe columns name the d1952 stand-in measure rather than IRD's definition; no producer exists yet (G8-r2c) and no active row requests them. Boundary diagnostics report weighted mass within $1 of every cut and the fixed-weight change under the left-closed alternative; publisher reclassification is unavailable.", + "tables": [ + { + "id": "ird_taxable_income_national_ty2024", + "entity": "person", + "currency": "NZD", + "input_unit": "integer_cent", + "income_column": "ird_taxable_income_proxy_cents", + "universe_column": "ird_taxable_income_proxy_universe_status", + "source_period": 2024, + "target_period": 2027, + "positive_band_closure": "right", + "nil_band": "present", + "negative_income_policy": "floor_zero", + "first_lower_cut_cents": 0, + "source_locator": "Income tables 2001-24!BE8:BE244", + "diagnostics": { + "boundary_window_cents": 100, + "alternative_positive_band_closure": "left" + }, + "bands": [ + { + "id": "row_8", + "kind": "nil", + "indicator": "taxable_income_band_row_8_indicator", + "source_label": "nil", + "count_reference": "ird_taxable_income_people_by_band__row_8", + "amount_reference": "ird_taxable_income_total_by_band__row_8" + }, + { + "id": "row_9", + "kind": "positive", + "upper_cent": 10000, + "indicator": "taxable_income_band_row_9_indicator", + "source_label": "$0.01 - $100", + "count_reference": "ird_taxable_income_people_by_band__row_9", + "amount_reference": "ird_taxable_income_total_by_band__row_9" + }, + { + "id": "row_10", + "kind": "positive", + "upper_cent": 100000, + "indicator": "taxable_income_band_row_10_indicator", + "source_label": "$101 - $1,000", + "count_reference": "ird_taxable_income_people_by_band__row_10", + "amount_reference": "ird_taxable_income_total_by_band__row_10" + }, + { + "id": "row_11", + "kind": "positive", + "upper_cent": 200000, + "indicator": "taxable_income_band_row_11_indicator", + "source_label": "$1,001 - $2,000", + "count_reference": "ird_taxable_income_people_by_band__row_11", + "amount_reference": "ird_taxable_income_total_by_band__row_11" + }, + { + "id": "row_12", + "kind": "positive", + "upper_cent": 300000, + "indicator": "taxable_income_band_row_12_indicator", + "source_label": "$2,001 - $3,000", + "count_reference": "ird_taxable_income_people_by_band__row_12", + "amount_reference": "ird_taxable_income_total_by_band__row_12" + }, + { + "id": "row_13", + "kind": "positive", + "upper_cent": 400000, + "indicator": "taxable_income_band_row_13_indicator", + "source_label": "$3,001 - $4,000", + "count_reference": "ird_taxable_income_people_by_band__row_13", + "amount_reference": "ird_taxable_income_total_by_band__row_13" + }, + { + "id": "row_14", + "kind": "positive", + "upper_cent": 500000, + "indicator": "taxable_income_band_row_14_indicator", + "source_label": "$4,001 - $5,000", + "count_reference": "ird_taxable_income_people_by_band__row_14", + "amount_reference": "ird_taxable_income_total_by_band__row_14" + }, + { + "id": "row_15", + "kind": "positive", + "upper_cent": 600000, + "indicator": "taxable_income_band_row_15_indicator", + "source_label": "$5,001 - $6,000", + "count_reference": "ird_taxable_income_people_by_band__row_15", + "amount_reference": "ird_taxable_income_total_by_band__row_15" + }, + { + "id": "row_16", + "kind": "positive", + "upper_cent": 700000, + "indicator": "taxable_income_band_row_16_indicator", + "source_label": "$6,001 - $7,000", + "count_reference": "ird_taxable_income_people_by_band__row_16", + "amount_reference": "ird_taxable_income_total_by_band__row_16" + }, + { + "id": "row_17", + "kind": "positive", + "upper_cent": 800000, + "indicator": "taxable_income_band_row_17_indicator", + "source_label": "$7,001 - $8,000", + "count_reference": "ird_taxable_income_people_by_band__row_17", + "amount_reference": "ird_taxable_income_total_by_band__row_17" + }, + { + "id": "row_18", + "kind": "positive", + "upper_cent": 900000, + "indicator": "taxable_income_band_row_18_indicator", + "source_label": "$8,001 - $9,000", + "count_reference": "ird_taxable_income_people_by_band__row_18", + "amount_reference": "ird_taxable_income_total_by_band__row_18" + }, + { + "id": "row_19", + "kind": "positive", + "upper_cent": 1000000, + "indicator": "taxable_income_band_row_19_indicator", + "source_label": "$9,001 - $10,000", + "count_reference": "ird_taxable_income_people_by_band__row_19", + "amount_reference": "ird_taxable_income_total_by_band__row_19" + }, + { + "id": "row_20", + "kind": "positive", + "upper_cent": 1100000, + "indicator": "taxable_income_band_row_20_indicator", + "source_label": "$10,001 - $11,000", + "count_reference": "ird_taxable_income_people_by_band__row_20", + "amount_reference": "ird_taxable_income_total_by_band__row_20" + }, + { + "id": "row_21", + "kind": "positive", + "upper_cent": 1200000, + "indicator": "taxable_income_band_row_21_indicator", + "source_label": "$11,001 - $12,000", + "count_reference": "ird_taxable_income_people_by_band__row_21", + "amount_reference": "ird_taxable_income_total_by_band__row_21" + }, + { + "id": "row_22", + "kind": "positive", + "upper_cent": 1300000, + "indicator": "taxable_income_band_row_22_indicator", + "source_label": "$12,001 - $13,000", + "count_reference": "ird_taxable_income_people_by_band__row_22", + "amount_reference": "ird_taxable_income_total_by_band__row_22" + }, + { + "id": "row_23", + "kind": "positive", + "upper_cent": 1400000, + "indicator": "taxable_income_band_row_23_indicator", + "source_label": "$13,001 - $14,000", + "count_reference": "ird_taxable_income_people_by_band__row_23", + "amount_reference": "ird_taxable_income_total_by_band__row_23" + }, + { + "id": "row_24", + "kind": "positive", + "upper_cent": 1500000, + "indicator": "taxable_income_band_row_24_indicator", + "source_label": "$14,001 - $15,000", + "count_reference": "ird_taxable_income_people_by_band__row_24", + "amount_reference": "ird_taxable_income_total_by_band__row_24" + }, + { + "id": "row_25", + "kind": "positive", + "upper_cent": 1600000, + "indicator": "taxable_income_band_row_25_indicator", + "source_label": "$15,001 - $16,000", + "count_reference": "ird_taxable_income_people_by_band__row_25", + "amount_reference": "ird_taxable_income_total_by_band__row_25" + }, + { + "id": "row_26", + "kind": "positive", + "upper_cent": 1700000, + "indicator": "taxable_income_band_row_26_indicator", + "source_label": "$16,001 - $17,000", + "count_reference": "ird_taxable_income_people_by_band__row_26", + "amount_reference": "ird_taxable_income_total_by_band__row_26" + }, + { + "id": "row_27", + "kind": "positive", + "upper_cent": 1800000, + "indicator": "taxable_income_band_row_27_indicator", + "source_label": "$17,001 - $18,000", + "count_reference": "ird_taxable_income_people_by_band__row_27", + "amount_reference": "ird_taxable_income_total_by_band__row_27" + }, + { + "id": "row_28", + "kind": "positive", + "upper_cent": 1900000, + "indicator": "taxable_income_band_row_28_indicator", + "source_label": "$18,001 - $19,000", + "count_reference": "ird_taxable_income_people_by_band__row_28", + "amount_reference": "ird_taxable_income_total_by_band__row_28" + }, + { + "id": "row_29", + "kind": "positive", + "upper_cent": 2000000, + "indicator": "taxable_income_band_row_29_indicator", + "source_label": "$19,001 - $20,000", + "count_reference": "ird_taxable_income_people_by_band__row_29", + "amount_reference": "ird_taxable_income_total_by_band__row_29" + }, + { + "id": "row_30", + "kind": "positive", + "upper_cent": 2100000, + "indicator": "taxable_income_band_row_30_indicator", + "source_label": "$20,000 - $21,000", + "count_reference": "ird_taxable_income_people_by_band__row_30", + "amount_reference": "ird_taxable_income_total_by_band__row_30" + }, + { + "id": "row_31", + "kind": "positive", + "upper_cent": 2200000, + "indicator": "taxable_income_band_row_31_indicator", + "source_label": "$21,001 - $22,000", + "count_reference": "ird_taxable_income_people_by_band__row_31", + "amount_reference": "ird_taxable_income_total_by_band__row_31" + }, + { + "id": "row_32", + "kind": "positive", + "upper_cent": 2300000, + "indicator": "taxable_income_band_row_32_indicator", + "source_label": "$22,001 - $23,000", + "count_reference": "ird_taxable_income_people_by_band__row_32", + "amount_reference": "ird_taxable_income_total_by_band__row_32" + }, + { + "id": "row_33", + "kind": "positive", + "upper_cent": 2400000, + "indicator": "taxable_income_band_row_33_indicator", + "source_label": "$23,001 - $24,000", + "count_reference": "ird_taxable_income_people_by_band__row_33", + "amount_reference": "ird_taxable_income_total_by_band__row_33" + }, + { + "id": "row_34", + "kind": "positive", + "upper_cent": 2500000, + "indicator": "taxable_income_band_row_34_indicator", + "source_label": "$24,001 - $25,000", + "count_reference": "ird_taxable_income_people_by_band__row_34", + "amount_reference": "ird_taxable_income_total_by_band__row_34" + }, + { + "id": "row_35", + "kind": "positive", + "upper_cent": 2600000, + "indicator": "taxable_income_band_row_35_indicator", + "source_label": "$25,001 - $26,000", + "count_reference": "ird_taxable_income_people_by_band__row_35", + "amount_reference": "ird_taxable_income_total_by_band__row_35" + }, + { + "id": "row_36", + "kind": "positive", + "upper_cent": 2700000, + "indicator": "taxable_income_band_row_36_indicator", + "source_label": "$26,001 - $27,000", + "count_reference": "ird_taxable_income_people_by_band__row_36", + "amount_reference": "ird_taxable_income_total_by_band__row_36" + }, + { + "id": "row_37", + "kind": "positive", + "upper_cent": 2800000, + "indicator": "taxable_income_band_row_37_indicator", + "source_label": "$27,001 - $28,000", + "count_reference": "ird_taxable_income_people_by_band__row_37", + "amount_reference": "ird_taxable_income_total_by_band__row_37" + }, + { + "id": "row_38", + "kind": "positive", + "upper_cent": 2900000, + "indicator": "taxable_income_band_row_38_indicator", + "source_label": "$28,001 - $29,000", + "count_reference": "ird_taxable_income_people_by_band__row_38", + "amount_reference": "ird_taxable_income_total_by_band__row_38" + }, + { + "id": "row_39", + "kind": "positive", + "upper_cent": 3000000, + "indicator": "taxable_income_band_row_39_indicator", + "source_label": "$29,001 - $30,000", + "count_reference": "ird_taxable_income_people_by_band__row_39", + "amount_reference": "ird_taxable_income_total_by_band__row_39" + }, + { + "id": "row_40", + "kind": "positive", + "upper_cent": 3100000, + "indicator": "taxable_income_band_row_40_indicator", + "source_label": "$30,001 - $31,000", + "count_reference": "ird_taxable_income_people_by_band__row_40", + "amount_reference": "ird_taxable_income_total_by_band__row_40" + }, + { + "id": "row_41", + "kind": "positive", + "upper_cent": 3200000, + "indicator": "taxable_income_band_row_41_indicator", + "source_label": "$31,001 - $32,000", + "count_reference": "ird_taxable_income_people_by_band__row_41", + "amount_reference": "ird_taxable_income_total_by_band__row_41" + }, + { + "id": "row_42", + "kind": "positive", + "upper_cent": 3300000, + "indicator": "taxable_income_band_row_42_indicator", + "source_label": "$32,001 - $33,000", + "count_reference": "ird_taxable_income_people_by_band__row_42", + "amount_reference": "ird_taxable_income_total_by_band__row_42" + }, + { + "id": "row_43", + "kind": "positive", + "upper_cent": 3400000, + "indicator": "taxable_income_band_row_43_indicator", + "source_label": "$33,001 - $34,000", + "count_reference": "ird_taxable_income_people_by_band__row_43", + "amount_reference": "ird_taxable_income_total_by_band__row_43" + }, + { + "id": "row_44", + "kind": "positive", + "upper_cent": 3500000, + "indicator": "taxable_income_band_row_44_indicator", + "source_label": "$34,001 - $35,000", + "count_reference": "ird_taxable_income_people_by_band__row_44", + "amount_reference": "ird_taxable_income_total_by_band__row_44" + }, + { + "id": "row_45", + "kind": "positive", + "upper_cent": 3600000, + "indicator": "taxable_income_band_row_45_indicator", + "source_label": "$35,001 - $36,000", + "count_reference": "ird_taxable_income_people_by_band__row_45", + "amount_reference": "ird_taxable_income_total_by_band__row_45" + }, + { + "id": "row_46", + "kind": "positive", + "upper_cent": 3700000, + "indicator": "taxable_income_band_row_46_indicator", + "source_label": "$36,001 - $37,000", + "count_reference": "ird_taxable_income_people_by_band__row_46", + "amount_reference": "ird_taxable_income_total_by_band__row_46" + }, + { + "id": "row_47", + "kind": "positive", + "upper_cent": 3800000, + "indicator": "taxable_income_band_row_47_indicator", + "source_label": "$37,001 - $38,000", + "count_reference": "ird_taxable_income_people_by_band__row_47", + "amount_reference": "ird_taxable_income_total_by_band__row_47" + }, + { + "id": "row_48", + "kind": "positive", + "upper_cent": 3900000, + "indicator": "taxable_income_band_row_48_indicator", + "source_label": "$38,001 - $39,000", + "count_reference": "ird_taxable_income_people_by_band__row_48", + "amount_reference": "ird_taxable_income_total_by_band__row_48" + }, + { + "id": "row_49", + "kind": "positive", + "upper_cent": 4000000, + "indicator": "taxable_income_band_row_49_indicator", + "source_label": "$39,001 - $40,000", + "count_reference": "ird_taxable_income_people_by_band__row_49", + "amount_reference": "ird_taxable_income_total_by_band__row_49" + }, + { + "id": "row_50", + "kind": "positive", + "upper_cent": 4100000, + "indicator": "taxable_income_band_row_50_indicator", + "source_label": "$40,001 - $41,000", + "count_reference": "ird_taxable_income_people_by_band__row_50", + "amount_reference": "ird_taxable_income_total_by_band__row_50" + }, + { + "id": "row_51", + "kind": "positive", + "upper_cent": 4200000, + "indicator": "taxable_income_band_row_51_indicator", + "source_label": "$41,001 - $42,000", + "count_reference": "ird_taxable_income_people_by_band__row_51", + "amount_reference": "ird_taxable_income_total_by_band__row_51" + }, + { + "id": "row_52", + "kind": "positive", + "upper_cent": 4300000, + "indicator": "taxable_income_band_row_52_indicator", + "source_label": "$42,001 - $43,000", + "count_reference": "ird_taxable_income_people_by_band__row_52", + "amount_reference": "ird_taxable_income_total_by_band__row_52" + }, + { + "id": "row_53", + "kind": "positive", + "upper_cent": 4400000, + "indicator": "taxable_income_band_row_53_indicator", + "source_label": "$43,001 - $44,000", + "count_reference": "ird_taxable_income_people_by_band__row_53", + "amount_reference": "ird_taxable_income_total_by_band__row_53" + }, + { + "id": "row_54", + "kind": "positive", + "upper_cent": 4500000, + "indicator": "taxable_income_band_row_54_indicator", + "source_label": "$44,001 - $45,000", + "count_reference": "ird_taxable_income_people_by_band__row_54", + "amount_reference": "ird_taxable_income_total_by_band__row_54" + }, + { + "id": "row_55", + "kind": "positive", + "upper_cent": 4600000, + "indicator": "taxable_income_band_row_55_indicator", + "source_label": "$45,001 - $46,000", + "count_reference": "ird_taxable_income_people_by_band__row_55", + "amount_reference": "ird_taxable_income_total_by_band__row_55" + }, + { + "id": "row_56", + "kind": "positive", + "upper_cent": 4700000, + "indicator": "taxable_income_band_row_56_indicator", + "source_label": "$46,001 - $47,000", + "count_reference": "ird_taxable_income_people_by_band__row_56", + "amount_reference": "ird_taxable_income_total_by_band__row_56" + }, + { + "id": "row_57", + "kind": "positive", + "upper_cent": 4800000, + "indicator": "taxable_income_band_row_57_indicator", + "source_label": "$47,001 - $48,000", + "count_reference": "ird_taxable_income_people_by_band__row_57", + "amount_reference": "ird_taxable_income_total_by_band__row_57" + }, + { + "id": "row_58", + "kind": "positive", + "upper_cent": 4900000, + "indicator": "taxable_income_band_row_58_indicator", + "source_label": "$48,001 - $49,000", + "count_reference": "ird_taxable_income_people_by_band__row_58", + "amount_reference": "ird_taxable_income_total_by_band__row_58" + }, + { + "id": "row_59", + "kind": "positive", + "upper_cent": 5000000, + "indicator": "taxable_income_band_row_59_indicator", + "source_label": "$49,001 - $50,000", + "count_reference": "ird_taxable_income_people_by_band__row_59", + "amount_reference": "ird_taxable_income_total_by_band__row_59" + }, + { + "id": "row_60", + "kind": "positive", + "upper_cent": 5100000, + "indicator": "taxable_income_band_row_60_indicator", + "source_label": "$50,000 - $51,000", + "count_reference": "ird_taxable_income_people_by_band__row_60", + "amount_reference": "ird_taxable_income_total_by_band__row_60" + }, + { + "id": "row_61", + "kind": "positive", + "upper_cent": 5200000, + "indicator": "taxable_income_band_row_61_indicator", + "source_label": "$51,001 - $52,000", + "count_reference": "ird_taxable_income_people_by_band__row_61", + "amount_reference": "ird_taxable_income_total_by_band__row_61" + }, + { + "id": "row_62", + "kind": "positive", + "upper_cent": 5300000, + "indicator": "taxable_income_band_row_62_indicator", + "source_label": "$52,001 - $53,000", + "count_reference": "ird_taxable_income_people_by_band__row_62", + "amount_reference": "ird_taxable_income_total_by_band__row_62" + }, + { + "id": "row_63", + "kind": "positive", + "upper_cent": 5400000, + "indicator": "taxable_income_band_row_63_indicator", + "source_label": "$53,001 - $54,000", + "count_reference": "ird_taxable_income_people_by_band__row_63", + "amount_reference": "ird_taxable_income_total_by_band__row_63" + }, + { + "id": "row_64", + "kind": "positive", + "upper_cent": 5500000, + "indicator": "taxable_income_band_row_64_indicator", + "source_label": "$54,001 - $55,000", + "count_reference": "ird_taxable_income_people_by_band__row_64", + "amount_reference": "ird_taxable_income_total_by_band__row_64" + }, + { + "id": "row_65", + "kind": "positive", + "upper_cent": 5600000, + "indicator": "taxable_income_band_row_65_indicator", + "source_label": "$55,001 - $56,000", + "count_reference": "ird_taxable_income_people_by_band__row_65", + "amount_reference": "ird_taxable_income_total_by_band__row_65" + }, + { + "id": "row_66", + "kind": "positive", + "upper_cent": 5700000, + "indicator": "taxable_income_band_row_66_indicator", + "source_label": "$56,001 - $57,000", + "count_reference": "ird_taxable_income_people_by_band__row_66", + "amount_reference": "ird_taxable_income_total_by_band__row_66" + }, + { + "id": "row_67", + "kind": "positive", + "upper_cent": 5800000, + "indicator": "taxable_income_band_row_67_indicator", + "source_label": "$57,001 - $58,000", + "count_reference": "ird_taxable_income_people_by_band__row_67", + "amount_reference": "ird_taxable_income_total_by_band__row_67" + }, + { + "id": "row_68", + "kind": "positive", + "upper_cent": 5900000, + "indicator": "taxable_income_band_row_68_indicator", + "source_label": "$58,001 - $59,000", + "count_reference": "ird_taxable_income_people_by_band__row_68", + "amount_reference": "ird_taxable_income_total_by_band__row_68" + }, + { + "id": "row_69", + "kind": "positive", + "upper_cent": 6000000, + "indicator": "taxable_income_band_row_69_indicator", + "source_label": "$59,001 - $60,000", + "count_reference": "ird_taxable_income_people_by_band__row_69", + "amount_reference": "ird_taxable_income_total_by_band__row_69" + }, + { + "id": "row_70", + "kind": "positive", + "upper_cent": 6100000, + "indicator": "taxable_income_band_row_70_indicator", + "source_label": "$60,001 - $61,000", + "count_reference": "ird_taxable_income_people_by_band__row_70", + "amount_reference": "ird_taxable_income_total_by_band__row_70" + }, + { + "id": "row_71", + "kind": "positive", + "upper_cent": 6200000, + "indicator": "taxable_income_band_row_71_indicator", + "source_label": "$61,001 - $62,000", + "count_reference": "ird_taxable_income_people_by_band__row_71", + "amount_reference": "ird_taxable_income_total_by_band__row_71" + }, + { + "id": "row_72", + "kind": "positive", + "upper_cent": 6300000, + "indicator": "taxable_income_band_row_72_indicator", + "source_label": "$62,001 - $63,000", + "count_reference": "ird_taxable_income_people_by_band__row_72", + "amount_reference": "ird_taxable_income_total_by_band__row_72" + }, + { + "id": "row_73", + "kind": "positive", + "upper_cent": 6400000, + "indicator": "taxable_income_band_row_73_indicator", + "source_label": "$63,001 - $64,000", + "count_reference": "ird_taxable_income_people_by_band__row_73", + "amount_reference": "ird_taxable_income_total_by_band__row_73" + }, + { + "id": "row_74", + "kind": "positive", + "upper_cent": 6500000, + "indicator": "taxable_income_band_row_74_indicator", + "source_label": "$64,001 - $65,000", + "count_reference": "ird_taxable_income_people_by_band__row_74", + "amount_reference": "ird_taxable_income_total_by_band__row_74" + }, + { + "id": "row_75", + "kind": "positive", + "upper_cent": 6600000, + "indicator": "taxable_income_band_row_75_indicator", + "source_label": "$65,001 - $66,000", + "count_reference": "ird_taxable_income_people_by_band__row_75", + "amount_reference": "ird_taxable_income_total_by_band__row_75" + }, + { + "id": "row_76", + "kind": "positive", + "upper_cent": 6700000, + "indicator": "taxable_income_band_row_76_indicator", + "source_label": "$66,001 - $67,000", + "count_reference": "ird_taxable_income_people_by_band__row_76", + "amount_reference": "ird_taxable_income_total_by_band__row_76" + }, + { + "id": "row_77", + "kind": "positive", + "upper_cent": 6800000, + "indicator": "taxable_income_band_row_77_indicator", + "source_label": "$67,001 - $68,000", + "count_reference": "ird_taxable_income_people_by_band__row_77", + "amount_reference": "ird_taxable_income_total_by_band__row_77" + }, + { + "id": "row_78", + "kind": "positive", + "upper_cent": 6900000, + "indicator": "taxable_income_band_row_78_indicator", + "source_label": "$68,001 - $69,000", + "count_reference": "ird_taxable_income_people_by_band__row_78", + "amount_reference": "ird_taxable_income_total_by_band__row_78" + }, + { + "id": "row_79", + "kind": "positive", + "upper_cent": 7000000, + "indicator": "taxable_income_band_row_79_indicator", + "source_label": "$69,001 - $70,000", + "count_reference": "ird_taxable_income_people_by_band__row_79", + "amount_reference": "ird_taxable_income_total_by_band__row_79" + }, + { + "id": "row_80", + "kind": "positive", + "upper_cent": 7100000, + "indicator": "taxable_income_band_row_80_indicator", + "source_label": "$70,001 - $71,000", + "count_reference": "ird_taxable_income_people_by_band__row_80", + "amount_reference": "ird_taxable_income_total_by_band__row_80" + }, + { + "id": "row_81", + "kind": "positive", + "upper_cent": 7200000, + "indicator": "taxable_income_band_row_81_indicator", + "source_label": "$71,001 - $72,000", + "count_reference": "ird_taxable_income_people_by_band__row_81", + "amount_reference": "ird_taxable_income_total_by_band__row_81" + }, + { + "id": "row_82", + "kind": "positive", + "upper_cent": 7300000, + "indicator": "taxable_income_band_row_82_indicator", + "source_label": "$72,001 - $73,000", + "count_reference": "ird_taxable_income_people_by_band__row_82", + "amount_reference": "ird_taxable_income_total_by_band__row_82" + }, + { + "id": "row_83", + "kind": "positive", + "upper_cent": 7400000, + "indicator": "taxable_income_band_row_83_indicator", + "source_label": "$73,001 - $74,000", + "count_reference": "ird_taxable_income_people_by_band__row_83", + "amount_reference": "ird_taxable_income_total_by_band__row_83" + }, + { + "id": "row_84", + "kind": "positive", + "upper_cent": 7500000, + "indicator": "taxable_income_band_row_84_indicator", + "source_label": "$74,001 - $75,000", + "count_reference": "ird_taxable_income_people_by_band__row_84", + "amount_reference": "ird_taxable_income_total_by_band__row_84" + }, + { + "id": "row_85", + "kind": "positive", + "upper_cent": 7600000, + "indicator": "taxable_income_band_row_85_indicator", + "source_label": "$75,001 - $76,000", + "count_reference": "ird_taxable_income_people_by_band__row_85", + "amount_reference": "ird_taxable_income_total_by_band__row_85" + }, + { + "id": "row_86", + "kind": "positive", + "upper_cent": 7700000, + "indicator": "taxable_income_band_row_86_indicator", + "source_label": "$76,001 - $77,000", + "count_reference": "ird_taxable_income_people_by_band__row_86", + "amount_reference": "ird_taxable_income_total_by_band__row_86" + }, + { + "id": "row_87", + "kind": "positive", + "upper_cent": 7800000, + "indicator": "taxable_income_band_row_87_indicator", + "source_label": "$77,001 - $78,000", + "count_reference": "ird_taxable_income_people_by_band__row_87", + "amount_reference": "ird_taxable_income_total_by_band__row_87" + }, + { + "id": "row_88", + "kind": "positive", + "upper_cent": 7900000, + "indicator": "taxable_income_band_row_88_indicator", + "source_label": "$78,001 - $79,000", + "count_reference": "ird_taxable_income_people_by_band__row_88", + "amount_reference": "ird_taxable_income_total_by_band__row_88" + }, + { + "id": "row_89", + "kind": "positive", + "upper_cent": 8000000, + "indicator": "taxable_income_band_row_89_indicator", + "source_label": "$79,001 - $80,000", + "count_reference": "ird_taxable_income_people_by_band__row_89", + "amount_reference": "ird_taxable_income_total_by_band__row_89" + }, + { + "id": "row_90", + "kind": "positive", + "upper_cent": 8100000, + "indicator": "taxable_income_band_row_90_indicator", + "source_label": "$80,000 - $81,000", + "count_reference": "ird_taxable_income_people_by_band__row_90", + "amount_reference": "ird_taxable_income_total_by_band__row_90" + }, + { + "id": "row_91", + "kind": "positive", + "upper_cent": 8200000, + "indicator": "taxable_income_band_row_91_indicator", + "source_label": "$81,001 - $82,000", + "count_reference": "ird_taxable_income_people_by_band__row_91", + "amount_reference": "ird_taxable_income_total_by_band__row_91" + }, + { + "id": "row_92", + "kind": "positive", + "upper_cent": 8300000, + "indicator": "taxable_income_band_row_92_indicator", + "source_label": "$82,001 - $83,000", + "count_reference": "ird_taxable_income_people_by_band__row_92", + "amount_reference": "ird_taxable_income_total_by_band__row_92" + }, + { + "id": "row_93", + "kind": "positive", + "upper_cent": 8400000, + "indicator": "taxable_income_band_row_93_indicator", + "source_label": "$83,001 - $84,000", + "count_reference": "ird_taxable_income_people_by_band__row_93", + "amount_reference": "ird_taxable_income_total_by_band__row_93" + }, + { + "id": "row_94", + "kind": "positive", + "upper_cent": 8500000, + "indicator": "taxable_income_band_row_94_indicator", + "source_label": "$84,001 - $85,000", + "count_reference": "ird_taxable_income_people_by_band__row_94", + "amount_reference": "ird_taxable_income_total_by_band__row_94" + }, + { + "id": "row_95", + "kind": "positive", + "upper_cent": 8600000, + "indicator": "taxable_income_band_row_95_indicator", + "source_label": "$85,001 - $86,000", + "count_reference": "ird_taxable_income_people_by_band__row_95", + "amount_reference": "ird_taxable_income_total_by_band__row_95" + }, + { + "id": "row_96", + "kind": "positive", + "upper_cent": 8700000, + "indicator": "taxable_income_band_row_96_indicator", + "source_label": "$86,001 - $87,000", + "count_reference": "ird_taxable_income_people_by_band__row_96", + "amount_reference": "ird_taxable_income_total_by_band__row_96" + }, + { + "id": "row_97", + "kind": "positive", + "upper_cent": 8800000, + "indicator": "taxable_income_band_row_97_indicator", + "source_label": "$87,001 - $88,000", + "count_reference": "ird_taxable_income_people_by_band__row_97", + "amount_reference": "ird_taxable_income_total_by_band__row_97" + }, + { + "id": "row_98", + "kind": "positive", + "upper_cent": 8900000, + "indicator": "taxable_income_band_row_98_indicator", + "source_label": "$88,001 - $89,000", + "count_reference": "ird_taxable_income_people_by_band__row_98", + "amount_reference": "ird_taxable_income_total_by_band__row_98" + }, + { + "id": "row_99", + "kind": "positive", + "upper_cent": 9000000, + "indicator": "taxable_income_band_row_99_indicator", + "source_label": "$89,001 - $90,000", + "count_reference": "ird_taxable_income_people_by_band__row_99", + "amount_reference": "ird_taxable_income_total_by_band__row_99" + }, + { + "id": "row_100", + "kind": "positive", + "upper_cent": 9100000, + "indicator": "taxable_income_band_row_100_indicator", + "source_label": "$90,001 - $91,000", + "count_reference": "ird_taxable_income_people_by_band__row_100", + "amount_reference": "ird_taxable_income_total_by_band__row_100" + }, + { + "id": "row_101", + "kind": "positive", + "upper_cent": 9200000, + "indicator": "taxable_income_band_row_101_indicator", + "source_label": "$91,001 - $92,000", + "count_reference": "ird_taxable_income_people_by_band__row_101", + "amount_reference": "ird_taxable_income_total_by_band__row_101" + }, + { + "id": "row_102", + "kind": "positive", + "upper_cent": 9300000, + "indicator": "taxable_income_band_row_102_indicator", + "source_label": "$92,001 - $93,000", + "count_reference": "ird_taxable_income_people_by_band__row_102", + "amount_reference": "ird_taxable_income_total_by_band__row_102" + }, + { + "id": "row_103", + "kind": "positive", + "upper_cent": 9400000, + "indicator": "taxable_income_band_row_103_indicator", + "source_label": "$93,001 - $94,000", + "count_reference": "ird_taxable_income_people_by_band__row_103", + "amount_reference": "ird_taxable_income_total_by_band__row_103" + }, + { + "id": "row_104", + "kind": "positive", + "upper_cent": 9500000, + "indicator": "taxable_income_band_row_104_indicator", + "source_label": "$94,001 - $95,000", + "count_reference": "ird_taxable_income_people_by_band__row_104", + "amount_reference": "ird_taxable_income_total_by_band__row_104" + }, + { + "id": "row_105", + "kind": "positive", + "upper_cent": 9600000, + "indicator": "taxable_income_band_row_105_indicator", + "source_label": "$95,001 - $96,000", + "count_reference": "ird_taxable_income_people_by_band__row_105", + "amount_reference": "ird_taxable_income_total_by_band__row_105" + }, + { + "id": "row_106", + "kind": "positive", + "upper_cent": 9700000, + "indicator": "taxable_income_band_row_106_indicator", + "source_label": "$96,001 - $97,000", + "count_reference": "ird_taxable_income_people_by_band__row_106", + "amount_reference": "ird_taxable_income_total_by_band__row_106" + }, + { + "id": "row_107", + "kind": "positive", + "upper_cent": 9800000, + "indicator": "taxable_income_band_row_107_indicator", + "source_label": "$97,001 - $98,000", + "count_reference": "ird_taxable_income_people_by_band__row_107", + "amount_reference": "ird_taxable_income_total_by_band__row_107" + }, + { + "id": "row_108", + "kind": "positive", + "upper_cent": 9900000, + "indicator": "taxable_income_band_row_108_indicator", + "source_label": "$98,001 - $99,000", + "count_reference": "ird_taxable_income_people_by_band__row_108", + "amount_reference": "ird_taxable_income_total_by_band__row_108" + }, + { + "id": "row_109", + "kind": "positive", + "upper_cent": 10000000, + "indicator": "taxable_income_band_row_109_indicator", + "source_label": "$99,001 - $100,000", + "count_reference": "ird_taxable_income_people_by_band__row_109", + "amount_reference": "ird_taxable_income_total_by_band__row_109" + }, + { + "id": "row_110", + "kind": "positive", + "upper_cent": 10100000, + "indicator": "taxable_income_band_row_110_indicator", + "source_label": "$100,001 - $101,000", + "count_reference": "ird_taxable_income_people_by_band__row_110", + "amount_reference": "ird_taxable_income_total_by_band__row_110" + }, + { + "id": "row_111", + "kind": "positive", + "upper_cent": 10200000, + "indicator": "taxable_income_band_row_111_indicator", + "source_label": "$101,001 - $102,000", + "count_reference": "ird_taxable_income_people_by_band__row_111", + "amount_reference": "ird_taxable_income_total_by_band__row_111" + }, + { + "id": "row_112", + "kind": "positive", + "upper_cent": 10300000, + "indicator": "taxable_income_band_row_112_indicator", + "source_label": "$102,001 - $103,000", + "count_reference": "ird_taxable_income_people_by_band__row_112", + "amount_reference": "ird_taxable_income_total_by_band__row_112" + }, + { + "id": "row_113", + "kind": "positive", + "upper_cent": 10400000, + "indicator": "taxable_income_band_row_113_indicator", + "source_label": "$103,001 - $104,000", + "count_reference": "ird_taxable_income_people_by_band__row_113", + "amount_reference": "ird_taxable_income_total_by_band__row_113" + }, + { + "id": "row_114", + "kind": "positive", + "upper_cent": 10500000, + "indicator": "taxable_income_band_row_114_indicator", + "source_label": "$104,001 - $105,000", + "count_reference": "ird_taxable_income_people_by_band__row_114", + "amount_reference": "ird_taxable_income_total_by_band__row_114" + }, + { + "id": "row_115", + "kind": "positive", + "upper_cent": 10600000, + "indicator": "taxable_income_band_row_115_indicator", + "source_label": "$105,001 - $106,000", + "count_reference": "ird_taxable_income_people_by_band__row_115", + "amount_reference": "ird_taxable_income_total_by_band__row_115" + }, + { + "id": "row_116", + "kind": "positive", + "upper_cent": 10700000, + "indicator": "taxable_income_band_row_116_indicator", + "source_label": "$106,001 - $107,000", + "count_reference": "ird_taxable_income_people_by_band__row_116", + "amount_reference": "ird_taxable_income_total_by_band__row_116" + }, + { + "id": "row_117", + "kind": "positive", + "upper_cent": 10800000, + "indicator": "taxable_income_band_row_117_indicator", + "source_label": "$107,001 - $108,000", + "count_reference": "ird_taxable_income_people_by_band__row_117", + "amount_reference": "ird_taxable_income_total_by_band__row_117" + }, + { + "id": "row_118", + "kind": "positive", + "upper_cent": 10900000, + "indicator": "taxable_income_band_row_118_indicator", + "source_label": "$108,001 - $109,000", + "count_reference": "ird_taxable_income_people_by_band__row_118", + "amount_reference": "ird_taxable_income_total_by_band__row_118" + }, + { + "id": "row_119", + "kind": "positive", + "upper_cent": 11000000, + "indicator": "taxable_income_band_row_119_indicator", + "source_label": "$109,001 - $110,000", + "count_reference": "ird_taxable_income_people_by_band__row_119", + "amount_reference": "ird_taxable_income_total_by_band__row_119" + }, + { + "id": "row_120", + "kind": "positive", + "upper_cent": 11100000, + "indicator": "taxable_income_band_row_120_indicator", + "source_label": "$110,001 - $111,000", + "count_reference": "ird_taxable_income_people_by_band__row_120", + "amount_reference": "ird_taxable_income_total_by_band__row_120" + }, + { + "id": "row_121", + "kind": "positive", + "upper_cent": 11200000, + "indicator": "taxable_income_band_row_121_indicator", + "source_label": "$111,001 - $112,000", + "count_reference": "ird_taxable_income_people_by_band__row_121", + "amount_reference": "ird_taxable_income_total_by_band__row_121" + }, + { + "id": "row_122", + "kind": "positive", + "upper_cent": 11300000, + "indicator": "taxable_income_band_row_122_indicator", + "source_label": "$112,001 - $113,000", + "count_reference": "ird_taxable_income_people_by_band__row_122", + "amount_reference": "ird_taxable_income_total_by_band__row_122" + }, + { + "id": "row_123", + "kind": "positive", + "upper_cent": 11400000, + "indicator": "taxable_income_band_row_123_indicator", + "source_label": "$113,001 - $114,000", + "count_reference": "ird_taxable_income_people_by_band__row_123", + "amount_reference": "ird_taxable_income_total_by_band__row_123" + }, + { + "id": "row_124", + "kind": "positive", + "upper_cent": 11500000, + "indicator": "taxable_income_band_row_124_indicator", + "source_label": "$114,001 - $115,000", + "count_reference": "ird_taxable_income_people_by_band__row_124", + "amount_reference": "ird_taxable_income_total_by_band__row_124" + }, + { + "id": "row_125", + "kind": "positive", + "upper_cent": 11600000, + "indicator": "taxable_income_band_row_125_indicator", + "source_label": "$115,001 - $116,000", + "count_reference": "ird_taxable_income_people_by_band__row_125", + "amount_reference": "ird_taxable_income_total_by_band__row_125" + }, + { + "id": "row_126", + "kind": "positive", + "upper_cent": 11700000, + "indicator": "taxable_income_band_row_126_indicator", + "source_label": "$116,001 - $117,000", + "count_reference": "ird_taxable_income_people_by_band__row_126", + "amount_reference": "ird_taxable_income_total_by_band__row_126" + }, + { + "id": "row_127", + "kind": "positive", + "upper_cent": 11800000, + "indicator": "taxable_income_band_row_127_indicator", + "source_label": "$117,001 - $118,000", + "count_reference": "ird_taxable_income_people_by_band__row_127", + "amount_reference": "ird_taxable_income_total_by_band__row_127" + }, + { + "id": "row_128", + "kind": "positive", + "upper_cent": 11900000, + "indicator": "taxable_income_band_row_128_indicator", + "source_label": "$118,001 - $119,000", + "count_reference": "ird_taxable_income_people_by_band__row_128", + "amount_reference": "ird_taxable_income_total_by_band__row_128" + }, + { + "id": "row_129", + "kind": "positive", + "upper_cent": 12000000, + "indicator": "taxable_income_band_row_129_indicator", + "source_label": "$119,001 - $120,000", + "count_reference": "ird_taxable_income_people_by_band__row_129", + "amount_reference": "ird_taxable_income_total_by_band__row_129" + }, + { + "id": "row_130", + "kind": "positive", + "upper_cent": 12100000, + "indicator": "taxable_income_band_row_130_indicator", + "source_label": "$120,001 - $121,000", + "count_reference": "ird_taxable_income_people_by_band__row_130", + "amount_reference": "ird_taxable_income_total_by_band__row_130" + }, + { + "id": "row_131", + "kind": "positive", + "upper_cent": 12200000, + "indicator": "taxable_income_band_row_131_indicator", + "source_label": "$121,001 - $122,000", + "count_reference": "ird_taxable_income_people_by_band__row_131", + "amount_reference": "ird_taxable_income_total_by_band__row_131" + }, + { + "id": "row_132", + "kind": "positive", + "upper_cent": 12300000, + "indicator": "taxable_income_band_row_132_indicator", + "source_label": "$122,001 - $123,000", + "count_reference": "ird_taxable_income_people_by_band__row_132", + "amount_reference": "ird_taxable_income_total_by_band__row_132" + }, + { + "id": "row_133", + "kind": "positive", + "upper_cent": 12400000, + "indicator": "taxable_income_band_row_133_indicator", + "source_label": "$123,001 - $124,000", + "count_reference": "ird_taxable_income_people_by_band__row_133", + "amount_reference": "ird_taxable_income_total_by_band__row_133" + }, + { + "id": "row_134", + "kind": "positive", + "upper_cent": 12500000, + "indicator": "taxable_income_band_row_134_indicator", + "source_label": "$124,001 - $125,000", + "count_reference": "ird_taxable_income_people_by_band__row_134", + "amount_reference": "ird_taxable_income_total_by_band__row_134" + }, + { + "id": "row_135", + "kind": "positive", + "upper_cent": 12600000, + "indicator": "taxable_income_band_row_135_indicator", + "source_label": "$125,001 - $126,000", + "count_reference": "ird_taxable_income_people_by_band__row_135", + "amount_reference": "ird_taxable_income_total_by_band__row_135" + }, + { + "id": "row_136", + "kind": "positive", + "upper_cent": 12700000, + "indicator": "taxable_income_band_row_136_indicator", + "source_label": "$126,001 - $127,000", + "count_reference": "ird_taxable_income_people_by_band__row_136", + "amount_reference": "ird_taxable_income_total_by_band__row_136" + }, + { + "id": "row_137", + "kind": "positive", + "upper_cent": 12800000, + "indicator": "taxable_income_band_row_137_indicator", + "source_label": "$127,001 - $128,000", + "count_reference": "ird_taxable_income_people_by_band__row_137", + "amount_reference": "ird_taxable_income_total_by_band__row_137" + }, + { + "id": "row_138", + "kind": "positive", + "upper_cent": 12900000, + "indicator": "taxable_income_band_row_138_indicator", + "source_label": "$128,001 - $129,000", + "count_reference": "ird_taxable_income_people_by_band__row_138", + "amount_reference": "ird_taxable_income_total_by_band__row_138" + }, + { + "id": "row_139", + "kind": "positive", + "upper_cent": 13000000, + "indicator": "taxable_income_band_row_139_indicator", + "source_label": "$129,001 - $130,000", + "count_reference": "ird_taxable_income_people_by_band__row_139", + "amount_reference": "ird_taxable_income_total_by_band__row_139" + }, + { + "id": "row_140", + "kind": "positive", + "upper_cent": 13100000, + "indicator": "taxable_income_band_row_140_indicator", + "source_label": "$130,001 - $131,000", + "count_reference": "ird_taxable_income_people_by_band__row_140", + "amount_reference": "ird_taxable_income_total_by_band__row_140" + }, + { + "id": "row_141", + "kind": "positive", + "upper_cent": 13200000, + "indicator": "taxable_income_band_row_141_indicator", + "source_label": "$131,001 - $132,000", + "count_reference": "ird_taxable_income_people_by_band__row_141", + "amount_reference": "ird_taxable_income_total_by_band__row_141" + }, + { + "id": "row_142", + "kind": "positive", + "upper_cent": 13300000, + "indicator": "taxable_income_band_row_142_indicator", + "source_label": "$132,001 - $133,000", + "count_reference": "ird_taxable_income_people_by_band__row_142", + "amount_reference": "ird_taxable_income_total_by_band__row_142" + }, + { + "id": "row_143", + "kind": "positive", + "upper_cent": 13400000, + "indicator": "taxable_income_band_row_143_indicator", + "source_label": "$133,001 - $134,000", + "count_reference": "ird_taxable_income_people_by_band__row_143", + "amount_reference": "ird_taxable_income_total_by_band__row_143" + }, + { + "id": "row_144", + "kind": "positive", + "upper_cent": 13500000, + "indicator": "taxable_income_band_row_144_indicator", + "source_label": "$134,001 - $135,000", + "count_reference": "ird_taxable_income_people_by_band__row_144", + "amount_reference": "ird_taxable_income_total_by_band__row_144" + }, + { + "id": "row_145", + "kind": "positive", + "upper_cent": 13600000, + "indicator": "taxable_income_band_row_145_indicator", + "source_label": "$135,001 - $136,000", + "count_reference": "ird_taxable_income_people_by_band__row_145", + "amount_reference": "ird_taxable_income_total_by_band__row_145" + }, + { + "id": "row_146", + "kind": "positive", + "upper_cent": 13700000, + "indicator": "taxable_income_band_row_146_indicator", + "source_label": "$136,001 - $137,000", + "count_reference": "ird_taxable_income_people_by_band__row_146", + "amount_reference": "ird_taxable_income_total_by_band__row_146" + }, + { + "id": "row_147", + "kind": "positive", + "upper_cent": 13800000, + "indicator": "taxable_income_band_row_147_indicator", + "source_label": "$137,001 - $138,000", + "count_reference": "ird_taxable_income_people_by_band__row_147", + "amount_reference": "ird_taxable_income_total_by_band__row_147" + }, + { + "id": "row_148", + "kind": "positive", + "upper_cent": 13900000, + "indicator": "taxable_income_band_row_148_indicator", + "source_label": "$138,001 - $139,000", + "count_reference": "ird_taxable_income_people_by_band__row_148", + "amount_reference": "ird_taxable_income_total_by_band__row_148" + }, + { + "id": "row_149", + "kind": "positive", + "upper_cent": 14000000, + "indicator": "taxable_income_band_row_149_indicator", + "source_label": "$139,001 - $140,000", + "count_reference": "ird_taxable_income_people_by_band__row_149", + "amount_reference": "ird_taxable_income_total_by_band__row_149" + }, + { + "id": "row_150", + "kind": "positive", + "upper_cent": 14100000, + "indicator": "taxable_income_band_row_150_indicator", + "source_label": "$140,001 - $141,000", + "count_reference": "ird_taxable_income_people_by_band__row_150", + "amount_reference": "ird_taxable_income_total_by_band__row_150" + }, + { + "id": "row_151", + "kind": "positive", + "upper_cent": 14200000, + "indicator": "taxable_income_band_row_151_indicator", + "source_label": "$141,001 - $142,000", + "count_reference": "ird_taxable_income_people_by_band__row_151", + "amount_reference": "ird_taxable_income_total_by_band__row_151" + }, + { + "id": "row_152", + "kind": "positive", + "upper_cent": 14300000, + "indicator": "taxable_income_band_row_152_indicator", + "source_label": "$142,001 - $143,000", + "count_reference": "ird_taxable_income_people_by_band__row_152", + "amount_reference": "ird_taxable_income_total_by_band__row_152" + }, + { + "id": "row_153", + "kind": "positive", + "upper_cent": 14400000, + "indicator": "taxable_income_band_row_153_indicator", + "source_label": "$143,001 - $144,000", + "count_reference": "ird_taxable_income_people_by_band__row_153", + "amount_reference": "ird_taxable_income_total_by_band__row_153" + }, + { + "id": "row_154", + "kind": "positive", + "upper_cent": 14500000, + "indicator": "taxable_income_band_row_154_indicator", + "source_label": "$144,001 - $145,000", + "count_reference": "ird_taxable_income_people_by_band__row_154", + "amount_reference": "ird_taxable_income_total_by_band__row_154" + }, + { + "id": "row_155", + "kind": "positive", + "upper_cent": 14600000, + "indicator": "taxable_income_band_row_155_indicator", + "source_label": "$145,001 - $146,000", + "count_reference": "ird_taxable_income_people_by_band__row_155", + "amount_reference": "ird_taxable_income_total_by_band__row_155" + }, + { + "id": "row_156", + "kind": "positive", + "upper_cent": 14700000, + "indicator": "taxable_income_band_row_156_indicator", + "source_label": "$146,001 - $147,000", + "count_reference": "ird_taxable_income_people_by_band__row_156", + "amount_reference": "ird_taxable_income_total_by_band__row_156" + }, + { + "id": "row_157", + "kind": "positive", + "upper_cent": 14800000, + "indicator": "taxable_income_band_row_157_indicator", + "source_label": "$147,001 - $148,000", + "count_reference": "ird_taxable_income_people_by_band__row_157", + "amount_reference": "ird_taxable_income_total_by_band__row_157" + }, + { + "id": "row_158", + "kind": "positive", + "upper_cent": 14900000, + "indicator": "taxable_income_band_row_158_indicator", + "source_label": "$148,001 - $149,000", + "count_reference": "ird_taxable_income_people_by_band__row_158", + "amount_reference": "ird_taxable_income_total_by_band__row_158" + }, + { + "id": "row_159", + "kind": "positive", + "upper_cent": 15000000, + "indicator": "taxable_income_band_row_159_indicator", + "source_label": "$149,001 - $150,000", + "count_reference": "ird_taxable_income_people_by_band__row_159", + "amount_reference": "ird_taxable_income_total_by_band__row_159" + }, + { + "id": "row_160", + "kind": "positive", + "upper_cent": 15100000, + "indicator": "taxable_income_band_row_160_indicator", + "source_label": "$150,001 - $151,000", + "count_reference": "ird_taxable_income_people_by_band__row_160", + "amount_reference": "ird_taxable_income_total_by_band__row_160" + }, + { + "id": "row_161", + "kind": "positive", + "upper_cent": 15200000, + "indicator": "taxable_income_band_row_161_indicator", + "source_label": "$151,001 - $152,000", + "count_reference": "ird_taxable_income_people_by_band__row_161", + "amount_reference": "ird_taxable_income_total_by_band__row_161" + }, + { + "id": "row_162", + "kind": "positive", + "upper_cent": 15300000, + "indicator": "taxable_income_band_row_162_indicator", + "source_label": "$152,001 - $153,000", + "count_reference": "ird_taxable_income_people_by_band__row_162", + "amount_reference": "ird_taxable_income_total_by_band__row_162" + }, + { + "id": "row_163", + "kind": "positive", + "upper_cent": 15400000, + "indicator": "taxable_income_band_row_163_indicator", + "source_label": "$153,001 - $154,000", + "count_reference": "ird_taxable_income_people_by_band__row_163", + "amount_reference": "ird_taxable_income_total_by_band__row_163" + }, + { + "id": "row_164", + "kind": "positive", + "upper_cent": 15500000, + "indicator": "taxable_income_band_row_164_indicator", + "source_label": "$154,001 - $155,000", + "count_reference": "ird_taxable_income_people_by_band__row_164", + "amount_reference": "ird_taxable_income_total_by_band__row_164" + }, + { + "id": "row_165", + "kind": "positive", + "upper_cent": 15600000, + "indicator": "taxable_income_band_row_165_indicator", + "source_label": "$155,001 - $156,000", + "count_reference": "ird_taxable_income_people_by_band__row_165", + "amount_reference": "ird_taxable_income_total_by_band__row_165" + }, + { + "id": "row_166", + "kind": "positive", + "upper_cent": 15700000, + "indicator": "taxable_income_band_row_166_indicator", + "source_label": "$156,001 - $157,000", + "count_reference": "ird_taxable_income_people_by_band__row_166", + "amount_reference": "ird_taxable_income_total_by_band__row_166" + }, + { + "id": "row_167", + "kind": "positive", + "upper_cent": 15800000, + "indicator": "taxable_income_band_row_167_indicator", + "source_label": "$157,001 - $158,000", + "count_reference": "ird_taxable_income_people_by_band__row_167", + "amount_reference": "ird_taxable_income_total_by_band__row_167" + }, + { + "id": "row_168", + "kind": "positive", + "upper_cent": 15900000, + "indicator": "taxable_income_band_row_168_indicator", + "source_label": "$158,001 - $159,000", + "count_reference": "ird_taxable_income_people_by_band__row_168", + "amount_reference": "ird_taxable_income_total_by_band__row_168" + }, + { + "id": "row_169", + "kind": "positive", + "upper_cent": 16000000, + "indicator": "taxable_income_band_row_169_indicator", + "source_label": "$159,001 - $160,000", + "count_reference": "ird_taxable_income_people_by_band__row_169", + "amount_reference": "ird_taxable_income_total_by_band__row_169" + }, + { + "id": "row_170", + "kind": "positive", + "upper_cent": 16100000, + "indicator": "taxable_income_band_row_170_indicator", + "source_label": "$160,001 - $161,000", + "count_reference": "ird_taxable_income_people_by_band__row_170", + "amount_reference": "ird_taxable_income_total_by_band__row_170" + }, + { + "id": "row_171", + "kind": "positive", + "upper_cent": 16200000, + "indicator": "taxable_income_band_row_171_indicator", + "source_label": "$161,001 - $162,000", + "count_reference": "ird_taxable_income_people_by_band__row_171", + "amount_reference": "ird_taxable_income_total_by_band__row_171" + }, + { + "id": "row_172", + "kind": "positive", + "upper_cent": 16300000, + "indicator": "taxable_income_band_row_172_indicator", + "source_label": "$162,001 - $163,000", + "count_reference": "ird_taxable_income_people_by_band__row_172", + "amount_reference": "ird_taxable_income_total_by_band__row_172" + }, + { + "id": "row_173", + "kind": "positive", + "upper_cent": 16400000, + "indicator": "taxable_income_band_row_173_indicator", + "source_label": "$163,001 - $164,000", + "count_reference": "ird_taxable_income_people_by_band__row_173", + "amount_reference": "ird_taxable_income_total_by_band__row_173" + }, + { + "id": "row_174", + "kind": "positive", + "upper_cent": 16500000, + "indicator": "taxable_income_band_row_174_indicator", + "source_label": "$164,001 - $165,000", + "count_reference": "ird_taxable_income_people_by_band__row_174", + "amount_reference": "ird_taxable_income_total_by_band__row_174" + }, + { + "id": "row_175", + "kind": "positive", + "upper_cent": 16600000, + "indicator": "taxable_income_band_row_175_indicator", + "source_label": "$165,001 - $166,000", + "count_reference": "ird_taxable_income_people_by_band__row_175", + "amount_reference": "ird_taxable_income_total_by_band__row_175" + }, + { + "id": "row_176", + "kind": "positive", + "upper_cent": 16700000, + "indicator": "taxable_income_band_row_176_indicator", + "source_label": "$166,001 - $167,000", + "count_reference": "ird_taxable_income_people_by_band__row_176", + "amount_reference": "ird_taxable_income_total_by_band__row_176" + }, + { + "id": "row_177", + "kind": "positive", + "upper_cent": 16800000, + "indicator": "taxable_income_band_row_177_indicator", + "source_label": "$167,001 - $168,000", + "count_reference": "ird_taxable_income_people_by_band__row_177", + "amount_reference": "ird_taxable_income_total_by_band__row_177" + }, + { + "id": "row_178", + "kind": "positive", + "upper_cent": 16900000, + "indicator": "taxable_income_band_row_178_indicator", + "source_label": "$168,001 - $169,000", + "count_reference": "ird_taxable_income_people_by_band__row_178", + "amount_reference": "ird_taxable_income_total_by_band__row_178" + }, + { + "id": "row_179", + "kind": "positive", + "upper_cent": 17000000, + "indicator": "taxable_income_band_row_179_indicator", + "source_label": "$169,001 - $170,000", + "count_reference": "ird_taxable_income_people_by_band__row_179", + "amount_reference": "ird_taxable_income_total_by_band__row_179" + }, + { + "id": "row_180", + "kind": "positive", + "upper_cent": 17100000, + "indicator": "taxable_income_band_row_180_indicator", + "source_label": "$170,001 - $171,000", + "count_reference": "ird_taxable_income_people_by_band__row_180", + "amount_reference": "ird_taxable_income_total_by_band__row_180" + }, + { + "id": "row_181", + "kind": "positive", + "upper_cent": 17200000, + "indicator": "taxable_income_band_row_181_indicator", + "source_label": "$171,001 - $172,000", + "count_reference": "ird_taxable_income_people_by_band__row_181", + "amount_reference": "ird_taxable_income_total_by_band__row_181" + }, + { + "id": "row_182", + "kind": "positive", + "upper_cent": 17300000, + "indicator": "taxable_income_band_row_182_indicator", + "source_label": "$172,001 - $173,000", + "count_reference": "ird_taxable_income_people_by_band__row_182", + "amount_reference": "ird_taxable_income_total_by_band__row_182" + }, + { + "id": "row_183", + "kind": "positive", + "upper_cent": 17400000, + "indicator": "taxable_income_band_row_183_indicator", + "source_label": "$173,001 - $174,000", + "count_reference": "ird_taxable_income_people_by_band__row_183", + "amount_reference": "ird_taxable_income_total_by_band__row_183" + }, + { + "id": "row_184", + "kind": "positive", + "upper_cent": 17500000, + "indicator": "taxable_income_band_row_184_indicator", + "source_label": "$174,001 - $175,000", + "count_reference": "ird_taxable_income_people_by_band__row_184", + "amount_reference": "ird_taxable_income_total_by_band__row_184" + }, + { + "id": "row_185", + "kind": "positive", + "upper_cent": 17600000, + "indicator": "taxable_income_band_row_185_indicator", + "source_label": "$175,001 - $176,000", + "count_reference": "ird_taxable_income_people_by_band__row_185", + "amount_reference": "ird_taxable_income_total_by_band__row_185" + }, + { + "id": "row_186", + "kind": "positive", + "upper_cent": 17700000, + "indicator": "taxable_income_band_row_186_indicator", + "source_label": "$176,001 - $177,000", + "count_reference": "ird_taxable_income_people_by_band__row_186", + "amount_reference": "ird_taxable_income_total_by_band__row_186" + }, + { + "id": "row_187", + "kind": "positive", + "upper_cent": 17800000, + "indicator": "taxable_income_band_row_187_indicator", + "source_label": "$177,001 - $178,000", + "count_reference": "ird_taxable_income_people_by_band__row_187", + "amount_reference": "ird_taxable_income_total_by_band__row_187" + }, + { + "id": "row_188", + "kind": "positive", + "upper_cent": 17900000, + "indicator": "taxable_income_band_row_188_indicator", + "source_label": "$178,001 - $179,000", + "count_reference": "ird_taxable_income_people_by_band__row_188", + "amount_reference": "ird_taxable_income_total_by_band__row_188" + }, + { + "id": "row_189", + "kind": "positive", + "upper_cent": 18000000, + "indicator": "taxable_income_band_row_189_indicator", + "source_label": "$179,001 - $180,000", + "count_reference": "ird_taxable_income_people_by_band__row_189", + "amount_reference": "ird_taxable_income_total_by_band__row_189" + }, + { + "id": "row_190", + "kind": "positive", + "upper_cent": 18100000, + "indicator": "taxable_income_band_row_190_indicator", + "source_label": "$180,001 - $181,000", + "count_reference": "ird_taxable_income_people_by_band__row_190", + "amount_reference": "ird_taxable_income_total_by_band__row_190" + }, + { + "id": "row_191", + "kind": "positive", + "upper_cent": 18200000, + "indicator": "taxable_income_band_row_191_indicator", + "source_label": "$181,001 - $182,000", + "count_reference": "ird_taxable_income_people_by_band__row_191", + "amount_reference": "ird_taxable_income_total_by_band__row_191" + }, + { + "id": "row_192", + "kind": "positive", + "upper_cent": 18300000, + "indicator": "taxable_income_band_row_192_indicator", + "source_label": "$182,001 - $183,000", + "count_reference": "ird_taxable_income_people_by_band__row_192", + "amount_reference": "ird_taxable_income_total_by_band__row_192" + }, + { + "id": "row_193", + "kind": "positive", + "upper_cent": 18400000, + "indicator": "taxable_income_band_row_193_indicator", + "source_label": "$183,001 - $184,000", + "count_reference": "ird_taxable_income_people_by_band__row_193", + "amount_reference": "ird_taxable_income_total_by_band__row_193" + }, + { + "id": "row_194", + "kind": "positive", + "upper_cent": 18500000, + "indicator": "taxable_income_band_row_194_indicator", + "source_label": "$184,001 - $185,000", + "count_reference": "ird_taxable_income_people_by_band__row_194", + "amount_reference": "ird_taxable_income_total_by_band__row_194" + }, + { + "id": "row_195", + "kind": "positive", + "upper_cent": 18600000, + "indicator": "taxable_income_band_row_195_indicator", + "source_label": "$185,001 - $186,000", + "count_reference": "ird_taxable_income_people_by_band__row_195", + "amount_reference": "ird_taxable_income_total_by_band__row_195" + }, + { + "id": "row_196", + "kind": "positive", + "upper_cent": 18700000, + "indicator": "taxable_income_band_row_196_indicator", + "source_label": "$186,001 - $187,000", + "count_reference": "ird_taxable_income_people_by_band__row_196", + "amount_reference": "ird_taxable_income_total_by_band__row_196" + }, + { + "id": "row_197", + "kind": "positive", + "upper_cent": 18800000, + "indicator": "taxable_income_band_row_197_indicator", + "source_label": "$187,001 - $188,000", + "count_reference": "ird_taxable_income_people_by_band__row_197", + "amount_reference": "ird_taxable_income_total_by_band__row_197" + }, + { + "id": "row_198", + "kind": "positive", + "upper_cent": 18900000, + "indicator": "taxable_income_band_row_198_indicator", + "source_label": "$188,001 - $189,000", + "count_reference": "ird_taxable_income_people_by_band__row_198", + "amount_reference": "ird_taxable_income_total_by_band__row_198" + }, + { + "id": "row_199", + "kind": "positive", + "upper_cent": 19000000, + "indicator": "taxable_income_band_row_199_indicator", + "source_label": "$189,001 - $190,000", + "count_reference": "ird_taxable_income_people_by_band__row_199", + "amount_reference": "ird_taxable_income_total_by_band__row_199" + }, + { + "id": "row_200", + "kind": "positive", + "upper_cent": 19100000, + "indicator": "taxable_income_band_row_200_indicator", + "source_label": "$190,001 - $191,000", + "count_reference": "ird_taxable_income_people_by_band__row_200", + "amount_reference": "ird_taxable_income_total_by_band__row_200" + }, + { + "id": "row_201", + "kind": "positive", + "upper_cent": 19200000, + "indicator": "taxable_income_band_row_201_indicator", + "source_label": "$191,001 - $192,000", + "count_reference": "ird_taxable_income_people_by_band__row_201", + "amount_reference": "ird_taxable_income_total_by_band__row_201" + }, + { + "id": "row_202", + "kind": "positive", + "upper_cent": 19300000, + "indicator": "taxable_income_band_row_202_indicator", + "source_label": "$192,001 - $193,000", + "count_reference": "ird_taxable_income_people_by_band__row_202", + "amount_reference": "ird_taxable_income_total_by_band__row_202" + }, + { + "id": "row_203", + "kind": "positive", + "upper_cent": 19400000, + "indicator": "taxable_income_band_row_203_indicator", + "source_label": "$193,001 - $194,000", + "count_reference": "ird_taxable_income_people_by_band__row_203", + "amount_reference": "ird_taxable_income_total_by_band__row_203" + }, + { + "id": "row_204", + "kind": "positive", + "upper_cent": 19500000, + "indicator": "taxable_income_band_row_204_indicator", + "source_label": "$194,001 - $195,000", + "count_reference": "ird_taxable_income_people_by_band__row_204", + "amount_reference": "ird_taxable_income_total_by_band__row_204" + }, + { + "id": "row_205", + "kind": "positive", + "upper_cent": 19600000, + "indicator": "taxable_income_band_row_205_indicator", + "source_label": "$195,001 - $196,000", + "count_reference": "ird_taxable_income_people_by_band__row_205", + "amount_reference": "ird_taxable_income_total_by_band__row_205" + }, + { + "id": "row_206", + "kind": "positive", + "upper_cent": 19700000, + "indicator": "taxable_income_band_row_206_indicator", + "source_label": "$196,001 - $197,000", + "count_reference": "ird_taxable_income_people_by_band__row_206", + "amount_reference": "ird_taxable_income_total_by_band__row_206" + }, + { + "id": "row_207", + "kind": "positive", + "upper_cent": 19800000, + "indicator": "taxable_income_band_row_207_indicator", + "source_label": "$197,001 - $198,000", + "count_reference": "ird_taxable_income_people_by_band__row_207", + "amount_reference": "ird_taxable_income_total_by_band__row_207" + }, + { + "id": "row_208", + "kind": "positive", + "upper_cent": 19900000, + "indicator": "taxable_income_band_row_208_indicator", + "source_label": "$198,001 - $199,000", + "count_reference": "ird_taxable_income_people_by_band__row_208", + "amount_reference": "ird_taxable_income_total_by_band__row_208" + }, + { + "id": "row_209", + "kind": "positive", + "upper_cent": 20000000, + "indicator": "taxable_income_band_row_209_indicator", + "source_label": "$199,001 - $200,000", + "count_reference": "ird_taxable_income_people_by_band__row_209", + "amount_reference": "ird_taxable_income_total_by_band__row_209" + }, + { + "id": "row_210", + "kind": "positive", + "upper_cent": 20500000, + "indicator": "taxable_income_band_row_210_indicator", + "source_label": "$200,001 - $205,000", + "count_reference": "ird_taxable_income_people_by_band__row_210", + "amount_reference": "ird_taxable_income_total_by_band__row_210" + }, + { + "id": "row_211", + "kind": "positive", + "upper_cent": 21000000, + "indicator": "taxable_income_band_row_211_indicator", + "source_label": "$205,001 - $210,000", + "count_reference": "ird_taxable_income_people_by_band__row_211", + "amount_reference": "ird_taxable_income_total_by_band__row_211" + }, + { + "id": "row_212", + "kind": "positive", + "upper_cent": 21500000, + "indicator": "taxable_income_band_row_212_indicator", + "source_label": "$210,001 - $215,000", + "count_reference": "ird_taxable_income_people_by_band__row_212", + "amount_reference": "ird_taxable_income_total_by_band__row_212" + }, + { + "id": "row_213", + "kind": "positive", + "upper_cent": 22000000, + "indicator": "taxable_income_band_row_213_indicator", + "source_label": "$215,001 - $220,000", + "count_reference": "ird_taxable_income_people_by_band__row_213", + "amount_reference": "ird_taxable_income_total_by_band__row_213" + }, + { + "id": "row_214", + "kind": "positive", + "upper_cent": 22500000, + "indicator": "taxable_income_band_row_214_indicator", + "source_label": "$220,001 - $225,000", + "count_reference": "ird_taxable_income_people_by_band__row_214", + "amount_reference": "ird_taxable_income_total_by_band__row_214" + }, + { + "id": "row_215", + "kind": "positive", + "upper_cent": 23000000, + "indicator": "taxable_income_band_row_215_indicator", + "source_label": "$225,001 - $230,000", + "count_reference": "ird_taxable_income_people_by_band__row_215", + "amount_reference": "ird_taxable_income_total_by_band__row_215" + }, + { + "id": "row_216", + "kind": "positive", + "upper_cent": 23500000, + "indicator": "taxable_income_band_row_216_indicator", + "source_label": "$230,001 - $235,000", + "count_reference": "ird_taxable_income_people_by_band__row_216", + "amount_reference": "ird_taxable_income_total_by_band__row_216" + }, + { + "id": "row_217", + "kind": "positive", + "upper_cent": 24000000, + "indicator": "taxable_income_band_row_217_indicator", + "source_label": "$235,001 - $240,000", + "count_reference": "ird_taxable_income_people_by_band__row_217", + "amount_reference": "ird_taxable_income_total_by_band__row_217" + }, + { + "id": "row_218", + "kind": "positive", + "upper_cent": 24500000, + "indicator": "taxable_income_band_row_218_indicator", + "source_label": "$240,001 - $245,000", + "count_reference": "ird_taxable_income_people_by_band__row_218", + "amount_reference": "ird_taxable_income_total_by_band__row_218" + }, + { + "id": "row_219", + "kind": "positive", + "upper_cent": 25000000, + "indicator": "taxable_income_band_row_219_indicator", + "source_label": "$245,001 - $250,000", + "count_reference": "ird_taxable_income_people_by_band__row_219", + "amount_reference": "ird_taxable_income_total_by_band__row_219" + }, + { + "id": "row_220", + "kind": "positive", + "upper_cent": 25500000, + "indicator": "taxable_income_band_row_220_indicator", + "source_label": "$250,001 - $255,000", + "count_reference": "ird_taxable_income_people_by_band__row_220", + "amount_reference": "ird_taxable_income_total_by_band__row_220" + }, + { + "id": "row_221", + "kind": "positive", + "upper_cent": 26000000, + "indicator": "taxable_income_band_row_221_indicator", + "source_label": "$255,001 - $260,000", + "count_reference": "ird_taxable_income_people_by_band__row_221", + "amount_reference": "ird_taxable_income_total_by_band__row_221" + }, + { + "id": "row_222", + "kind": "positive", + "upper_cent": 26500000, + "indicator": "taxable_income_band_row_222_indicator", + "source_label": "$260,001 - $265,000", + "count_reference": "ird_taxable_income_people_by_band__row_222", + "amount_reference": "ird_taxable_income_total_by_band__row_222" + }, + { + "id": "row_223", + "kind": "positive", + "upper_cent": 27000000, + "indicator": "taxable_income_band_row_223_indicator", + "source_label": "$265,001 - $270,000", + "count_reference": "ird_taxable_income_people_by_band__row_223", + "amount_reference": "ird_taxable_income_total_by_band__row_223" + }, + { + "id": "row_224", + "kind": "positive", + "upper_cent": 27500000, + "indicator": "taxable_income_band_row_224_indicator", + "source_label": "$270,001 - $275,000", + "count_reference": "ird_taxable_income_people_by_band__row_224", + "amount_reference": "ird_taxable_income_total_by_band__row_224" + }, + { + "id": "row_225", + "kind": "positive", + "upper_cent": 28000000, + "indicator": "taxable_income_band_row_225_indicator", + "source_label": "$275,001 - $280,000", + "count_reference": "ird_taxable_income_people_by_band__row_225", + "amount_reference": "ird_taxable_income_total_by_band__row_225" + }, + { + "id": "row_226", + "kind": "positive", + "upper_cent": 28500000, + "indicator": "taxable_income_band_row_226_indicator", + "source_label": "$280,001 - $285,000", + "count_reference": "ird_taxable_income_people_by_band__row_226", + "amount_reference": "ird_taxable_income_total_by_band__row_226" + }, + { + "id": "row_227", + "kind": "positive", + "upper_cent": 29000000, + "indicator": "taxable_income_band_row_227_indicator", + "source_label": "$285,001 - $290,000", + "count_reference": "ird_taxable_income_people_by_band__row_227", + "amount_reference": "ird_taxable_income_total_by_band__row_227" + }, + { + "id": "row_228", + "kind": "positive", + "upper_cent": 29500000, + "indicator": "taxable_income_band_row_228_indicator", + "source_label": "$290,001 - $295,000", + "count_reference": "ird_taxable_income_people_by_band__row_228", + "amount_reference": "ird_taxable_income_total_by_band__row_228" + }, + { + "id": "row_229", + "kind": "positive", + "upper_cent": 30000000, + "indicator": "taxable_income_band_row_229_indicator", + "source_label": "$295,001 - $300,000", + "count_reference": "ird_taxable_income_people_by_band__row_229", + "amount_reference": "ird_taxable_income_total_by_band__row_229" + }, + { + "id": "row_230", + "kind": "positive", + "upper_cent": 35000000, + "indicator": "taxable_income_band_row_230_indicator", + "source_label": "$300,000 - $350,000", + "count_reference": "ird_taxable_income_people_by_band__row_230", + "amount_reference": "ird_taxable_income_total_by_band__row_230" + }, + { + "id": "row_231", + "kind": "positive", + "upper_cent": 40000000, + "indicator": "taxable_income_band_row_231_indicator", + "source_label": "$350,001 - $400,000", + "count_reference": "ird_taxable_income_people_by_band__row_231", + "amount_reference": "ird_taxable_income_total_by_band__row_231" + }, + { + "id": "row_232", + "kind": "positive", + "upper_cent": 45000000, + "indicator": "taxable_income_band_row_232_indicator", + "source_label": "$400,001 - $450,000", + "count_reference": "ird_taxable_income_people_by_band__row_232", + "amount_reference": "ird_taxable_income_total_by_band__row_232" + }, + { + "id": "row_233", + "kind": "positive", + "upper_cent": 50000000, + "indicator": "taxable_income_band_row_233_indicator", + "source_label": "$450,001 - $500,000", + "count_reference": "ird_taxable_income_people_by_band__row_233", + "amount_reference": "ird_taxable_income_total_by_band__row_233" + }, + { + "id": "row_234", + "kind": "positive", + "upper_cent": 55000000, + "indicator": "taxable_income_band_row_234_indicator", + "source_label": "$500,001 - $550,000", + "count_reference": "ird_taxable_income_people_by_band__row_234", + "amount_reference": "ird_taxable_income_total_by_band__row_234" + }, + { + "id": "row_235", + "kind": "positive", + "upper_cent": 60000000, + "indicator": "taxable_income_band_row_235_indicator", + "source_label": "$550,001 - $600,000", + "count_reference": "ird_taxable_income_people_by_band__row_235", + "amount_reference": "ird_taxable_income_total_by_band__row_235" + }, + { + "id": "row_236", + "kind": "positive", + "upper_cent": 65000000, + "indicator": "taxable_income_band_row_236_indicator", + "source_label": "$600,001 - $650,000", + "count_reference": "ird_taxable_income_people_by_band__row_236", + "amount_reference": "ird_taxable_income_total_by_band__row_236" + }, + { + "id": "row_237", + "kind": "positive", + "upper_cent": 70000000, + "indicator": "taxable_income_band_row_237_indicator", + "source_label": "$650,001 - $700,000", + "count_reference": "ird_taxable_income_people_by_band__row_237", + "amount_reference": "ird_taxable_income_total_by_band__row_237" + }, + { + "id": "row_238", + "kind": "positive", + "upper_cent": 75000000, + "indicator": "taxable_income_band_row_238_indicator", + "source_label": "$700,001 - $750,000", + "count_reference": "ird_taxable_income_people_by_band__row_238", + "amount_reference": "ird_taxable_income_total_by_band__row_238" + }, + { + "id": "row_239", + "kind": "positive", + "upper_cent": 80000000, + "indicator": "taxable_income_band_row_239_indicator", + "source_label": "$750,001 - $800,000", + "count_reference": "ird_taxable_income_people_by_band__row_239", + "amount_reference": "ird_taxable_income_total_by_band__row_239" + }, + { + "id": "row_240", + "kind": "positive", + "upper_cent": 85000000, + "indicator": "taxable_income_band_row_240_indicator", + "source_label": "$800,001 - $850,000", + "count_reference": "ird_taxable_income_people_by_band__row_240", + "amount_reference": "ird_taxable_income_total_by_band__row_240" + }, + { + "id": "row_241", + "kind": "positive", + "upper_cent": 90000000, + "indicator": "taxable_income_band_row_241_indicator", + "source_label": "$850,001 - $900,000", + "count_reference": "ird_taxable_income_people_by_band__row_241", + "amount_reference": "ird_taxable_income_total_by_band__row_241" + }, + { + "id": "row_242", + "kind": "positive", + "upper_cent": 95000000, + "indicator": "taxable_income_band_row_242_indicator", + "source_label": "$900,001 - $950,000", + "count_reference": "ird_taxable_income_people_by_band__row_242", + "amount_reference": "ird_taxable_income_total_by_band__row_242" + }, + { + "id": "row_243", + "kind": "positive", + "upper_cent": 100000000, + "indicator": "taxable_income_band_row_243_indicator", + "source_label": "$950,001 - $1,000,000", + "count_reference": "ird_taxable_income_people_by_band__row_243", + "amount_reference": "ird_taxable_income_total_by_band__row_243" + }, + { + "id": "row_244", + "kind": "positive", + "upper_cent": null, + "indicator": "taxable_income_band_row_244_indicator", + "source_label": "Over $1,000,000", + "count_reference": "ird_taxable_income_people_by_band__row_244", + "amount_reference": "ird_taxable_income_total_by_band__row_244" + } + ], + "description": "National TY2024 taxable-income bands, rows 8-244: one nil band, 235 finite bands and the open tail over $1,000,000. Every band names its parked count and amount references." + }, + { + "id": "ird_taxable_income_age_ty2024", + "entity": "person", + "currency": "NZD", + "input_unit": "integer_cent", + "income_column": "ird_taxable_income_proxy_cents", + "universe_column": "ird_taxable_income_proxy_universe_status", + "source_period": 2024, + "target_period": 2027, + "positive_band_closure": "right", + "nil_band": "present", + "negative_income_policy": "floor_zero", + "first_lower_cut_cents": 0, + "source_locator": "A6:A188", + "diagnostics": { + "boundary_window_cents": 100, + "alternative_positive_band_closure": "left" + }, + "bands": [ + { + "id": "row_6", + "kind": "nil", + "indicator": "taxable_income_age_table_band_row_6_indicator", + "source_label": "nil" + }, + { + "id": "row_7", + "kind": "positive", + "upper_cent": 10000, + "indicator": "taxable_income_age_table_band_row_7_indicator", + "source_label": "$0.01 - $100" + }, + { + "id": "row_8", + "kind": "positive", + "upper_cent": 100000, + "indicator": "taxable_income_age_table_band_row_8_indicator", + "source_label": "$101 - $1,000" + }, + { + "id": "row_9", + "kind": "positive", + "upper_cent": 200000, + "indicator": "taxable_income_age_table_band_row_9_indicator", + "source_label": "$1,001 - $2,000" + }, + { + "id": "row_10", + "kind": "positive", + "upper_cent": 300000, + "indicator": "taxable_income_age_table_band_row_10_indicator", + "source_label": "$2,001 - $3,000" + }, + { + "id": "row_11", + "kind": "positive", + "upper_cent": 400000, + "indicator": "taxable_income_age_table_band_row_11_indicator", + "source_label": "$3,001 - $4,000" + }, + { + "id": "row_12", + "kind": "positive", + "upper_cent": 500000, + "indicator": "taxable_income_age_table_band_row_12_indicator", + "source_label": "$4,001 - $5,000" + }, + { + "id": "row_13", + "kind": "positive", + "upper_cent": 600000, + "indicator": "taxable_income_age_table_band_row_13_indicator", + "source_label": "$5,001 - $6,000" + }, + { + "id": "row_14", + "kind": "positive", + "upper_cent": 700000, + "indicator": "taxable_income_age_table_band_row_14_indicator", + "source_label": "$6,001 - $7,000" + }, + { + "id": "row_15", + "kind": "positive", + "upper_cent": 800000, + "indicator": "taxable_income_age_table_band_row_15_indicator", + "source_label": "$7,001 - $8,000" + }, + { + "id": "row_16", + "kind": "positive", + "upper_cent": 900000, + "indicator": "taxable_income_age_table_band_row_16_indicator", + "source_label": "$8,001 - $9,000" + }, + { + "id": "row_17", + "kind": "positive", + "upper_cent": 1000000, + "indicator": "taxable_income_age_table_band_row_17_indicator", + "source_label": "$9,001 - $10,000" + }, + { + "id": "row_18", + "kind": "positive", + "upper_cent": 1100000, + "indicator": "taxable_income_age_table_band_row_18_indicator", + "source_label": "$10,001 - $11,000" + }, + { + "id": "row_19", + "kind": "positive", + "upper_cent": 1200000, + "indicator": "taxable_income_age_table_band_row_19_indicator", + "source_label": "$11,001 - $12,000" + }, + { + "id": "row_20", + "kind": "positive", + "upper_cent": 1300000, + "indicator": "taxable_income_age_table_band_row_20_indicator", + "source_label": "$12,001 - $13,000" + }, + { + "id": "row_21", + "kind": "positive", + "upper_cent": 1400000, + "indicator": "taxable_income_age_table_band_row_21_indicator", + "source_label": "$13,001 - $14,000" + }, + { + "id": "row_22", + "kind": "positive", + "upper_cent": 1500000, + "indicator": "taxable_income_age_table_band_row_22_indicator", + "source_label": "$14,001 - $15,000" + }, + { + "id": "row_23", + "kind": "positive", + "upper_cent": 1600000, + "indicator": "taxable_income_age_table_band_row_23_indicator", + "source_label": "$15,001 - $16,000" + }, + { + "id": "row_24", + "kind": "positive", + "upper_cent": 1700000, + "indicator": "taxable_income_age_table_band_row_24_indicator", + "source_label": "$16,001 - $17,000" + }, + { + "id": "row_25", + "kind": "positive", + "upper_cent": 1800000, + "indicator": "taxable_income_age_table_band_row_25_indicator", + "source_label": "$17,001 - $18,000" + }, + { + "id": "row_26", + "kind": "positive", + "upper_cent": 1900000, + "indicator": "taxable_income_age_table_band_row_26_indicator", + "source_label": "$18,001 - $19,000" + }, + { + "id": "row_27", + "kind": "positive", + "upper_cent": 2000000, + "indicator": "taxable_income_age_table_band_row_27_indicator", + "source_label": "$19,001 - $20,000" + }, + { + "id": "row_28", + "kind": "positive", + "upper_cent": 2100000, + "indicator": "taxable_income_age_table_band_row_28_indicator", + "source_label": "$20,000 - $21,000" + }, + { + "id": "row_29", + "kind": "positive", + "upper_cent": 2200000, + "indicator": "taxable_income_age_table_band_row_29_indicator", + "source_label": "$21,001 - $22,000" + }, + { + "id": "row_30", + "kind": "positive", + "upper_cent": 2300000, + "indicator": "taxable_income_age_table_band_row_30_indicator", + "source_label": "$22,001 - $23,000" + }, + { + "id": "row_31", + "kind": "positive", + "upper_cent": 2400000, + "indicator": "taxable_income_age_table_band_row_31_indicator", + "source_label": "$23,001 - $24,000" + }, + { + "id": "row_32", + "kind": "positive", + "upper_cent": 2500000, + "indicator": "taxable_income_age_table_band_row_32_indicator", + "source_label": "$24,001 - $25,000" + }, + { + "id": "row_33", + "kind": "positive", + "upper_cent": 2600000, + "indicator": "taxable_income_age_table_band_row_33_indicator", + "source_label": "$25,001 - $26,000" + }, + { + "id": "row_34", + "kind": "positive", + "upper_cent": 2700000, + "indicator": "taxable_income_age_table_band_row_34_indicator", + "source_label": "$26,001 - $27,000" + }, + { + "id": "row_35", + "kind": "positive", + "upper_cent": 2800000, + "indicator": "taxable_income_age_table_band_row_35_indicator", + "source_label": "$27,001 - $28,000" + }, + { + "id": "row_36", + "kind": "positive", + "upper_cent": 2900000, + "indicator": "taxable_income_age_table_band_row_36_indicator", + "source_label": "$28,001 - $29,000" + }, + { + "id": "row_37", + "kind": "positive", + "upper_cent": 3000000, + "indicator": "taxable_income_age_table_band_row_37_indicator", + "source_label": "$29,001 - $30,000" + }, + { + "id": "row_38", + "kind": "positive", + "upper_cent": 3100000, + "indicator": "taxable_income_age_table_band_row_38_indicator", + "source_label": "$30,001 - $31,000" + }, + { + "id": "row_39", + "kind": "positive", + "upper_cent": 3200000, + "indicator": "taxable_income_age_table_band_row_39_indicator", + "source_label": "$31,001 - $32,000" + }, + { + "id": "row_40", + "kind": "positive", + "upper_cent": 3300000, + "indicator": "taxable_income_age_table_band_row_40_indicator", + "source_label": "$32,001 - $33,000" + }, + { + "id": "row_41", + "kind": "positive", + "upper_cent": 3400000, + "indicator": "taxable_income_age_table_band_row_41_indicator", + "source_label": "$33,001 - $34,000" + }, + { + "id": "row_42", + "kind": "positive", + "upper_cent": 3500000, + "indicator": "taxable_income_age_table_band_row_42_indicator", + "source_label": "$34,001 - $35,000" + }, + { + "id": "row_43", + "kind": "positive", + "upper_cent": 3600000, + "indicator": "taxable_income_age_table_band_row_43_indicator", + "source_label": "$35,001 - $36,000" + }, + { + "id": "row_44", + "kind": "positive", + "upper_cent": 3700000, + "indicator": "taxable_income_age_table_band_row_44_indicator", + "source_label": "$36,001 - $37,000" + }, + { + "id": "row_45", + "kind": "positive", + "upper_cent": 3800000, + "indicator": "taxable_income_age_table_band_row_45_indicator", + "source_label": "$37,001 - $38,000" + }, + { + "id": "row_46", + "kind": "positive", + "upper_cent": 3900000, + "indicator": "taxable_income_age_table_band_row_46_indicator", + "source_label": "$38,001 - $39,000" + }, + { + "id": "row_47", + "kind": "positive", + "upper_cent": 4000000, + "indicator": "taxable_income_age_table_band_row_47_indicator", + "source_label": "$39,001 - $40,000" + }, + { + "id": "row_48", + "kind": "positive", + "upper_cent": 4100000, + "indicator": "taxable_income_age_table_band_row_48_indicator", + "source_label": "$40,001 - $41,000" + }, + { + "id": "row_49", + "kind": "positive", + "upper_cent": 4200000, + "indicator": "taxable_income_age_table_band_row_49_indicator", + "source_label": "$41,001 - $42,000" + }, + { + "id": "row_50", + "kind": "positive", + "upper_cent": 4300000, + "indicator": "taxable_income_age_table_band_row_50_indicator", + "source_label": "$42,001 - $43,000" + }, + { + "id": "row_51", + "kind": "positive", + "upper_cent": 4400000, + "indicator": "taxable_income_age_table_band_row_51_indicator", + "source_label": "$43,001 - $44,000" + }, + { + "id": "row_52", + "kind": "positive", + "upper_cent": 4500000, + "indicator": "taxable_income_age_table_band_row_52_indicator", + "source_label": "$44,001 - $45,000" + }, + { + "id": "row_53", + "kind": "positive", + "upper_cent": 4600000, + "indicator": "taxable_income_age_table_band_row_53_indicator", + "source_label": "$45,001 - $46,000" + }, + { + "id": "row_54", + "kind": "positive", + "upper_cent": 4700000, + "indicator": "taxable_income_age_table_band_row_54_indicator", + "source_label": "$46,001 - $47,000" + }, + { + "id": "row_55", + "kind": "positive", + "upper_cent": 4800000, + "indicator": "taxable_income_age_table_band_row_55_indicator", + "source_label": "$47,001 - $48,000" + }, + { + "id": "row_56", + "kind": "positive", + "upper_cent": 4900000, + "indicator": "taxable_income_age_table_band_row_56_indicator", + "source_label": "$48,001 - $49,000" + }, + { + "id": "row_57", + "kind": "positive", + "upper_cent": 5000000, + "indicator": "taxable_income_age_table_band_row_57_indicator", + "source_label": "$49,001 - $50,000" + }, + { + "id": "row_58", + "kind": "positive", + "upper_cent": 5100000, + "indicator": "taxable_income_age_table_band_row_58_indicator", + "source_label": "$50,000 - $51,000" + }, + { + "id": "row_59", + "kind": "positive", + "upper_cent": 5200000, + "indicator": "taxable_income_age_table_band_row_59_indicator", + "source_label": "$51,001 - $52,000" + }, + { + "id": "row_60", + "kind": "positive", + "upper_cent": 5300000, + "indicator": "taxable_income_age_table_band_row_60_indicator", + "source_label": "$52,001 - $53,000" + }, + { + "id": "row_61", + "kind": "positive", + "upper_cent": 5400000, + "indicator": "taxable_income_age_table_band_row_61_indicator", + "source_label": "$53,001 - $54,000" + }, + { + "id": "row_62", + "kind": "positive", + "upper_cent": 5500000, + "indicator": "taxable_income_age_table_band_row_62_indicator", + "source_label": "$54,001 - $55,000" + }, + { + "id": "row_63", + "kind": "positive", + "upper_cent": 5600000, + "indicator": "taxable_income_age_table_band_row_63_indicator", + "source_label": "$55,001 - $56,000" + }, + { + "id": "row_64", + "kind": "positive", + "upper_cent": 5700000, + "indicator": "taxable_income_age_table_band_row_64_indicator", + "source_label": "$56,001 - $57,000" + }, + { + "id": "row_65", + "kind": "positive", + "upper_cent": 5800000, + "indicator": "taxable_income_age_table_band_row_65_indicator", + "source_label": "$57,001 - $58,000" + }, + { + "id": "row_66", + "kind": "positive", + "upper_cent": 5900000, + "indicator": "taxable_income_age_table_band_row_66_indicator", + "source_label": "$58,001 - $59,000" + }, + { + "id": "row_67", + "kind": "positive", + "upper_cent": 6000000, + "indicator": "taxable_income_age_table_band_row_67_indicator", + "source_label": "$59,001 - $60,000" + }, + { + "id": "row_68", + "kind": "positive", + "upper_cent": 6100000, + "indicator": "taxable_income_age_table_band_row_68_indicator", + "source_label": "$60,001 - $61,000" + }, + { + "id": "row_69", + "kind": "positive", + "upper_cent": 6200000, + "indicator": "taxable_income_age_table_band_row_69_indicator", + "source_label": "$61,001 - $62,000" + }, + { + "id": "row_70", + "kind": "positive", + "upper_cent": 6300000, + "indicator": "taxable_income_age_table_band_row_70_indicator", + "source_label": "$62,001 - $63,000" + }, + { + "id": "row_71", + "kind": "positive", + "upper_cent": 6400000, + "indicator": "taxable_income_age_table_band_row_71_indicator", + "source_label": "$63,001 - $64,000" + }, + { + "id": "row_72", + "kind": "positive", + "upper_cent": 6500000, + "indicator": "taxable_income_age_table_band_row_72_indicator", + "source_label": "$64,001 - $65,000" + }, + { + "id": "row_73", + "kind": "positive", + "upper_cent": 6600000, + "indicator": "taxable_income_age_table_band_row_73_indicator", + "source_label": "$65,001 - $66,000" + }, + { + "id": "row_74", + "kind": "positive", + "upper_cent": 6700000, + "indicator": "taxable_income_age_table_band_row_74_indicator", + "source_label": "$66,001 - $67,000" + }, + { + "id": "row_75", + "kind": "positive", + "upper_cent": 6800000, + "indicator": "taxable_income_age_table_band_row_75_indicator", + "source_label": "$67,001 - $68,000" + }, + { + "id": "row_76", + "kind": "positive", + "upper_cent": 6900000, + "indicator": "taxable_income_age_table_band_row_76_indicator", + "source_label": "$68,001 - $69,000" + }, + { + "id": "row_77", + "kind": "positive", + "upper_cent": 7000000, + "indicator": "taxable_income_age_table_band_row_77_indicator", + "source_label": "$69,001 - $70,000" + }, + { + "id": "row_78", + "kind": "positive", + "upper_cent": 7100000, + "indicator": "taxable_income_age_table_band_row_78_indicator", + "source_label": "$70,001 - $71,000" + }, + { + "id": "row_79", + "kind": "positive", + "upper_cent": 7200000, + "indicator": "taxable_income_age_table_band_row_79_indicator", + "source_label": "$71,001 - $72,000" + }, + { + "id": "row_80", + "kind": "positive", + "upper_cent": 7300000, + "indicator": "taxable_income_age_table_band_row_80_indicator", + "source_label": "$72,001 - $73,000" + }, + { + "id": "row_81", + "kind": "positive", + "upper_cent": 7400000, + "indicator": "taxable_income_age_table_band_row_81_indicator", + "source_label": "$73,001 - $74,000" + }, + { + "id": "row_82", + "kind": "positive", + "upper_cent": 7500000, + "indicator": "taxable_income_age_table_band_row_82_indicator", + "source_label": "$74,001 - $75,000" + }, + { + "id": "row_83", + "kind": "positive", + "upper_cent": 7600000, + "indicator": "taxable_income_age_table_band_row_83_indicator", + "source_label": "$75,001 - $76,000" + }, + { + "id": "row_84", + "kind": "positive", + "upper_cent": 7700000, + "indicator": "taxable_income_age_table_band_row_84_indicator", + "source_label": "$76,001 - $77,000" + }, + { + "id": "row_85", + "kind": "positive", + "upper_cent": 7800000, + "indicator": "taxable_income_age_table_band_row_85_indicator", + "source_label": "$77,001 - $78,000" + }, + { + "id": "row_86", + "kind": "positive", + "upper_cent": 7900000, + "indicator": "taxable_income_age_table_band_row_86_indicator", + "source_label": "$78,001 - $79,000" + }, + { + "id": "row_87", + "kind": "positive", + "upper_cent": 8000000, + "indicator": "taxable_income_age_table_band_row_87_indicator", + "source_label": "$79,001 - $80,000" + }, + { + "id": "row_88", + "kind": "positive", + "upper_cent": 8100000, + "indicator": "taxable_income_age_table_band_row_88_indicator", + "source_label": "$80,000 - $81,000" + }, + { + "id": "row_89", + "kind": "positive", + "upper_cent": 8200000, + "indicator": "taxable_income_age_table_band_row_89_indicator", + "source_label": "$81,001 - $82,000" + }, + { + "id": "row_90", + "kind": "positive", + "upper_cent": 8300000, + "indicator": "taxable_income_age_table_band_row_90_indicator", + "source_label": "$82,001 - $83,000" + }, + { + "id": "row_91", + "kind": "positive", + "upper_cent": 8400000, + "indicator": "taxable_income_age_table_band_row_91_indicator", + "source_label": "$83,001 - $84,000" + }, + { + "id": "row_92", + "kind": "positive", + "upper_cent": 8500000, + "indicator": "taxable_income_age_table_band_row_92_indicator", + "source_label": "$84,001 - $85,000" + }, + { + "id": "row_93", + "kind": "positive", + "upper_cent": 8600000, + "indicator": "taxable_income_age_table_band_row_93_indicator", + "source_label": "$85,001 - $86,000" + }, + { + "id": "row_94", + "kind": "positive", + "upper_cent": 8700000, + "indicator": "taxable_income_age_table_band_row_94_indicator", + "source_label": "$86,001 - $87,000" + }, + { + "id": "row_95", + "kind": "positive", + "upper_cent": 8800000, + "indicator": "taxable_income_age_table_band_row_95_indicator", + "source_label": "$87,001 - $88,000" + }, + { + "id": "row_96", + "kind": "positive", + "upper_cent": 8900000, + "indicator": "taxable_income_age_table_band_row_96_indicator", + "source_label": "$88,001 - $89,000" + }, + { + "id": "row_97", + "kind": "positive", + "upper_cent": 9000000, + "indicator": "taxable_income_age_table_band_row_97_indicator", + "source_label": "$89,001 - $90,000" + }, + { + "id": "row_98", + "kind": "positive", + "upper_cent": 9100000, + "indicator": "taxable_income_age_table_band_row_98_indicator", + "source_label": "$90,001 - $91,000" + }, + { + "id": "row_99", + "kind": "positive", + "upper_cent": 9200000, + "indicator": "taxable_income_age_table_band_row_99_indicator", + "source_label": "$91,001 - $92,000" + }, + { + "id": "row_100", + "kind": "positive", + "upper_cent": 9300000, + "indicator": "taxable_income_age_table_band_row_100_indicator", + "source_label": "$92,001 - $93,000" + }, + { + "id": "row_101", + "kind": "positive", + "upper_cent": 9400000, + "indicator": "taxable_income_age_table_band_row_101_indicator", + "source_label": "$93,001 - $94,000" + }, + { + "id": "row_102", + "kind": "positive", + "upper_cent": 9500000, + "indicator": "taxable_income_age_table_band_row_102_indicator", + "source_label": "$94,001 - $95,000" + }, + { + "id": "row_103", + "kind": "positive", + "upper_cent": 9600000, + "indicator": "taxable_income_age_table_band_row_103_indicator", + "source_label": "$95,001 - $96,000" + }, + { + "id": "row_104", + "kind": "positive", + "upper_cent": 9700000, + "indicator": "taxable_income_age_table_band_row_104_indicator", + "source_label": "$96,001 - $97,000" + }, + { + "id": "row_105", + "kind": "positive", + "upper_cent": 9800000, + "indicator": "taxable_income_age_table_band_row_105_indicator", + "source_label": "$97,001 - $98,000" + }, + { + "id": "row_106", + "kind": "positive", + "upper_cent": 9900000, + "indicator": "taxable_income_age_table_band_row_106_indicator", + "source_label": "$98,001 - $99,000" + }, + { + "id": "row_107", + "kind": "positive", + "upper_cent": 10000000, + "indicator": "taxable_income_age_table_band_row_107_indicator", + "source_label": "$99,001 - $100,000" + }, + { + "id": "row_108", + "kind": "positive", + "upper_cent": 10100000, + "indicator": "taxable_income_age_table_band_row_108_indicator", + "source_label": "$100,001 - $101,000" + }, + { + "id": "row_109", + "kind": "positive", + "upper_cent": 10200000, + "indicator": "taxable_income_age_table_band_row_109_indicator", + "source_label": "$101,001 - $102,000" + }, + { + "id": "row_110", + "kind": "positive", + "upper_cent": 10300000, + "indicator": "taxable_income_age_table_band_row_110_indicator", + "source_label": "$102,001 - $103,000" + }, + { + "id": "row_111", + "kind": "positive", + "upper_cent": 10400000, + "indicator": "taxable_income_age_table_band_row_111_indicator", + "source_label": "$103,001 - $104,000" + }, + { + "id": "row_112", + "kind": "positive", + "upper_cent": 10500000, + "indicator": "taxable_income_age_table_band_row_112_indicator", + "source_label": "$104,001 - $105,000" + }, + { + "id": "row_113", + "kind": "positive", + "upper_cent": 10600000, + "indicator": "taxable_income_age_table_band_row_113_indicator", + "source_label": "$105,001 - $106,000" + }, + { + "id": "row_114", + "kind": "positive", + "upper_cent": 10700000, + "indicator": "taxable_income_age_table_band_row_114_indicator", + "source_label": "$106,001 - $107,000" + }, + { + "id": "row_115", + "kind": "positive", + "upper_cent": 10800000, + "indicator": "taxable_income_age_table_band_row_115_indicator", + "source_label": "$107,001 - $108,000" + }, + { + "id": "row_116", + "kind": "positive", + "upper_cent": 10900000, + "indicator": "taxable_income_age_table_band_row_116_indicator", + "source_label": "$108,001 - $109,000" + }, + { + "id": "row_117", + "kind": "positive", + "upper_cent": 11000000, + "indicator": "taxable_income_age_table_band_row_117_indicator", + "source_label": "$109,001 - $110,000" + }, + { + "id": "row_118", + "kind": "positive", + "upper_cent": 11100000, + "indicator": "taxable_income_age_table_band_row_118_indicator", + "source_label": "$110,001 - $111,000" + }, + { + "id": "row_119", + "kind": "positive", + "upper_cent": 11200000, + "indicator": "taxable_income_age_table_band_row_119_indicator", + "source_label": "$111,001 - $112,000" + }, + { + "id": "row_120", + "kind": "positive", + "upper_cent": 11300000, + "indicator": "taxable_income_age_table_band_row_120_indicator", + "source_label": "$112,001 - $113,000" + }, + { + "id": "row_121", + "kind": "positive", + "upper_cent": 11400000, + "indicator": "taxable_income_age_table_band_row_121_indicator", + "source_label": "$113,001 - $114,000" + }, + { + "id": "row_122", + "kind": "positive", + "upper_cent": 11500000, + "indicator": "taxable_income_age_table_band_row_122_indicator", + "source_label": "$114,001 - $115,000" + }, + { + "id": "row_123", + "kind": "positive", + "upper_cent": 11600000, + "indicator": "taxable_income_age_table_band_row_123_indicator", + "source_label": "$115,001 - $116,000" + }, + { + "id": "row_124", + "kind": "positive", + "upper_cent": 11700000, + "indicator": "taxable_income_age_table_band_row_124_indicator", + "source_label": "$116,001 - $117,000" + }, + { + "id": "row_125", + "kind": "positive", + "upper_cent": 11800000, + "indicator": "taxable_income_age_table_band_row_125_indicator", + "source_label": "$117,001 - $118,000" + }, + { + "id": "row_126", + "kind": "positive", + "upper_cent": 11900000, + "indicator": "taxable_income_age_table_band_row_126_indicator", + "source_label": "$118,001 - $119,000" + }, + { + "id": "row_127", + "kind": "positive", + "upper_cent": 12000000, + "indicator": "taxable_income_age_table_band_row_127_indicator", + "source_label": "$119,001 - $120,000" + }, + { + "id": "row_128", + "kind": "positive", + "upper_cent": 12100000, + "indicator": "taxable_income_age_table_band_row_128_indicator", + "source_label": "$120,001 - $121,000" + }, + { + "id": "row_129", + "kind": "positive", + "upper_cent": 12200000, + "indicator": "taxable_income_age_table_band_row_129_indicator", + "source_label": "$121,001 - $122,000" + }, + { + "id": "row_130", + "kind": "positive", + "upper_cent": 12300000, + "indicator": "taxable_income_age_table_band_row_130_indicator", + "source_label": "$122,001 - $123,000" + }, + { + "id": "row_131", + "kind": "positive", + "upper_cent": 12400000, + "indicator": "taxable_income_age_table_band_row_131_indicator", + "source_label": "$123,001 - $124,000" + }, + { + "id": "row_132", + "kind": "positive", + "upper_cent": 12500000, + "indicator": "taxable_income_age_table_band_row_132_indicator", + "source_label": "$124,001 - $125,000" + }, + { + "id": "row_133", + "kind": "positive", + "upper_cent": 12600000, + "indicator": "taxable_income_age_table_band_row_133_indicator", + "source_label": "$125,001 - $126,000" + }, + { + "id": "row_134", + "kind": "positive", + "upper_cent": 12700000, + "indicator": "taxable_income_age_table_band_row_134_indicator", + "source_label": "$126,001 - $127,000" + }, + { + "id": "row_135", + "kind": "positive", + "upper_cent": 12800000, + "indicator": "taxable_income_age_table_band_row_135_indicator", + "source_label": "$127,001 - $128,000" + }, + { + "id": "row_136", + "kind": "positive", + "upper_cent": 12900000, + "indicator": "taxable_income_age_table_band_row_136_indicator", + "source_label": "$128,001 - $129,000" + }, + { + "id": "row_137", + "kind": "positive", + "upper_cent": 13000000, + "indicator": "taxable_income_age_table_band_row_137_indicator", + "source_label": "$129,001 - $130,000" + }, + { + "id": "row_138", + "kind": "positive", + "upper_cent": 13100000, + "indicator": "taxable_income_age_table_band_row_138_indicator", + "source_label": "$130,001 - $131,000" + }, + { + "id": "row_139", + "kind": "positive", + "upper_cent": 13200000, + "indicator": "taxable_income_age_table_band_row_139_indicator", + "source_label": "$131,001 - $132,000" + }, + { + "id": "row_140", + "kind": "positive", + "upper_cent": 13300000, + "indicator": "taxable_income_age_table_band_row_140_indicator", + "source_label": "$132,001 - $133,000" + }, + { + "id": "row_141", + "kind": "positive", + "upper_cent": 13400000, + "indicator": "taxable_income_age_table_band_row_141_indicator", + "source_label": "$133,001 - $134,000" + }, + { + "id": "row_142", + "kind": "positive", + "upper_cent": 13500000, + "indicator": "taxable_income_age_table_band_row_142_indicator", + "source_label": "$134,001 - $135,000" + }, + { + "id": "row_143", + "kind": "positive", + "upper_cent": 13600000, + "indicator": "taxable_income_age_table_band_row_143_indicator", + "source_label": "$135,001 - $136,000" + }, + { + "id": "row_144", + "kind": "positive", + "upper_cent": 13700000, + "indicator": "taxable_income_age_table_band_row_144_indicator", + "source_label": "$136,001 - $137,000" + }, + { + "id": "row_145", + "kind": "positive", + "upper_cent": 13800000, + "indicator": "taxable_income_age_table_band_row_145_indicator", + "source_label": "$137,001 - $138,000" + }, + { + "id": "row_146", + "kind": "positive", + "upper_cent": 13900000, + "indicator": "taxable_income_age_table_band_row_146_indicator", + "source_label": "$138,001 - $139,000" + }, + { + "id": "row_147", + "kind": "positive", + "upper_cent": 14000000, + "indicator": "taxable_income_age_table_band_row_147_indicator", + "source_label": "$139,001 - $140,000" + }, + { + "id": "row_148", + "kind": "positive", + "upper_cent": 14100000, + "indicator": "taxable_income_age_table_band_row_148_indicator", + "source_label": "$140,001 - $141,000" + }, + { + "id": "row_149", + "kind": "positive", + "upper_cent": 14200000, + "indicator": "taxable_income_age_table_band_row_149_indicator", + "source_label": "$141,001 - $142,000" + }, + { + "id": "row_150", + "kind": "positive", + "upper_cent": 14300000, + "indicator": "taxable_income_age_table_band_row_150_indicator", + "source_label": "$142,001 - $143,000" + }, + { + "id": "row_151", + "kind": "positive", + "upper_cent": 14400000, + "indicator": "taxable_income_age_table_band_row_151_indicator", + "source_label": "$143,001 - $144,000" + }, + { + "id": "row_152", + "kind": "positive", + "upper_cent": 14500000, + "indicator": "taxable_income_age_table_band_row_152_indicator", + "source_label": "$144,001 - $145,000" + }, + { + "id": "row_153", + "kind": "positive", + "upper_cent": 14600000, + "indicator": "taxable_income_age_table_band_row_153_indicator", + "source_label": "$145,001 - $146,000" + }, + { + "id": "row_154", + "kind": "positive", + "upper_cent": 14700000, + "indicator": "taxable_income_age_table_band_row_154_indicator", + "source_label": "$146,001 - $147,000" + }, + { + "id": "row_155", + "kind": "positive", + "upper_cent": 14800000, + "indicator": "taxable_income_age_table_band_row_155_indicator", + "source_label": "$147,001 - $148,000" + }, + { + "id": "row_156", + "kind": "positive", + "upper_cent": 14900000, + "indicator": "taxable_income_age_table_band_row_156_indicator", + "source_label": "$148,001 - $149,000" + }, + { + "id": "row_157", + "kind": "positive", + "upper_cent": 15000000, + "indicator": "taxable_income_age_table_band_row_157_indicator", + "source_label": "$149,001 - $150,000" + }, + { + "id": "row_158", + "kind": "positive", + "upper_cent": 15100000, + "indicator": "taxable_income_age_table_band_row_158_indicator", + "source_label": "$150,001 - $151,000" + }, + { + "id": "row_159", + "kind": "positive", + "upper_cent": 15200000, + "indicator": "taxable_income_age_table_band_row_159_indicator", + "source_label": "$151,001 - $152,000" + }, + { + "id": "row_160", + "kind": "positive", + "upper_cent": 15300000, + "indicator": "taxable_income_age_table_band_row_160_indicator", + "source_label": "$152,001 - $153,000" + }, + { + "id": "row_161", + "kind": "positive", + "upper_cent": 15400000, + "indicator": "taxable_income_age_table_band_row_161_indicator", + "source_label": "$153,001 - $154,000" + }, + { + "id": "row_162", + "kind": "positive", + "upper_cent": 15500000, + "indicator": "taxable_income_age_table_band_row_162_indicator", + "source_label": "$154,001 - $155,000" + }, + { + "id": "row_163", + "kind": "positive", + "upper_cent": 15600000, + "indicator": "taxable_income_age_table_band_row_163_indicator", + "source_label": "$155,001 - $156,000" + }, + { + "id": "row_164", + "kind": "positive", + "upper_cent": 15700000, + "indicator": "taxable_income_age_table_band_row_164_indicator", + "source_label": "$156,001 - $157,000" + }, + { + "id": "row_165", + "kind": "positive", + "upper_cent": 15800000, + "indicator": "taxable_income_age_table_band_row_165_indicator", + "source_label": "$157,001 - $158,000" + }, + { + "id": "row_166", + "kind": "positive", + "upper_cent": 15900000, + "indicator": "taxable_income_age_table_band_row_166_indicator", + "source_label": "$158,001 - $159,000" + }, + { + "id": "row_167", + "kind": "positive", + "upper_cent": 16000000, + "indicator": "taxable_income_age_table_band_row_167_indicator", + "source_label": "$159,001 - $160,000" + }, + { + "id": "row_168", + "kind": "positive", + "upper_cent": 16100000, + "indicator": "taxable_income_age_table_band_row_168_indicator", + "source_label": "$160,001 - $161,000" + }, + { + "id": "row_169", + "kind": "positive", + "upper_cent": 16200000, + "indicator": "taxable_income_age_table_band_row_169_indicator", + "source_label": "$161,001 - $162,000" + }, + { + "id": "row_170", + "kind": "positive", + "upper_cent": 16300000, + "indicator": "taxable_income_age_table_band_row_170_indicator", + "source_label": "$162,001 - $163,000" + }, + { + "id": "row_171", + "kind": "positive", + "upper_cent": 16400000, + "indicator": "taxable_income_age_table_band_row_171_indicator", + "source_label": "$163,001 - $164,000" + }, + { + "id": "row_172", + "kind": "positive", + "upper_cent": 16500000, + "indicator": "taxable_income_age_table_band_row_172_indicator", + "source_label": "$164,001 - $165,000" + }, + { + "id": "row_173", + "kind": "positive", + "upper_cent": 16600000, + "indicator": "taxable_income_age_table_band_row_173_indicator", + "source_label": "$165,001 - $166,000" + }, + { + "id": "row_174", + "kind": "positive", + "upper_cent": 16700000, + "indicator": "taxable_income_age_table_band_row_174_indicator", + "source_label": "$166,001 - $167,000" + }, + { + "id": "row_175", + "kind": "positive", + "upper_cent": 16800000, + "indicator": "taxable_income_age_table_band_row_175_indicator", + "source_label": "$167,001 - $168,000" + }, + { + "id": "row_176", + "kind": "positive", + "upper_cent": 16900000, + "indicator": "taxable_income_age_table_band_row_176_indicator", + "source_label": "$168,001 - $169,000" + }, + { + "id": "row_177", + "kind": "positive", + "upper_cent": 17000000, + "indicator": "taxable_income_age_table_band_row_177_indicator", + "source_label": "$169,001 - $170,000" + }, + { + "id": "row_178", + "kind": "positive", + "upper_cent": 17100000, + "indicator": "taxable_income_age_table_band_row_178_indicator", + "source_label": "$170,001 - $171,000" + }, + { + "id": "row_179", + "kind": "positive", + "upper_cent": 17200000, + "indicator": "taxable_income_age_table_band_row_179_indicator", + "source_label": "$171,001 - $172,000" + }, + { + "id": "row_180", + "kind": "positive", + "upper_cent": 17300000, + "indicator": "taxable_income_age_table_band_row_180_indicator", + "source_label": "$172,001 - $173,000" + }, + { + "id": "row_181", + "kind": "positive", + "upper_cent": 17400000, + "indicator": "taxable_income_age_table_band_row_181_indicator", + "source_label": "$173,001 - $174,000" + }, + { + "id": "row_182", + "kind": "positive", + "upper_cent": 17500000, + "indicator": "taxable_income_age_table_band_row_182_indicator", + "source_label": "$174,001 - $175,000" + }, + { + "id": "row_183", + "kind": "positive", + "upper_cent": 17600000, + "indicator": "taxable_income_age_table_band_row_183_indicator", + "source_label": "$175,001 - $176,000" + }, + { + "id": "row_184", + "kind": "positive", + "upper_cent": 17700000, + "indicator": "taxable_income_age_table_band_row_184_indicator", + "source_label": "$176,001 - $177,000" + }, + { + "id": "row_185", + "kind": "positive", + "upper_cent": 17800000, + "indicator": "taxable_income_age_table_band_row_185_indicator", + "source_label": "$177,001 - $178,000" + }, + { + "id": "row_186", + "kind": "positive", + "upper_cent": 17900000, + "indicator": "taxable_income_age_table_band_row_186_indicator", + "source_label": "$178,001 - $179,000" + }, + { + "id": "row_187", + "kind": "positive", + "upper_cent": 18000000, + "indicator": "taxable_income_age_table_band_row_187_indicator", + "source_label": "$179,001 - $180,000" + }, + { + "id": "row_188", + "kind": "positive", + "upper_cent": null, + "indicator": "taxable_income_age_table_band_row_188_indicator", + "source_label": "Over $180,000" + } + ], + "description": "Age-by-income TY2024 taxable-income bands, rows 6-188: one nil band, 181 finite bands and the open tail over $180,000. Declared and validated only; no reference companions and no fit rows." + } + ] +} diff --git a/packages/microcosm-build/src/microcosm/build/nz/reference_inventory.json b/packages/microcosm-build/src/microcosm/build/nz/reference_inventory.json index bc33e7a400..cb5c0e7635 100644 --- a/packages/microcosm-build/src/microcosm/build/nz/reference_inventory.json +++ b/packages/microcosm-build/src/microcosm/build/nz/reference_inventory.json @@ -36,7 +36,7 @@ "active": 64, "requires_reference_profile_resolution": 170, "requires_census_family_nucleus_standard": 51, - "requires_g8r2_taxable_income_contract_intervals_and_ageing": 474, + "requires_prerequisites": 474, "requires_stratified_receipt_assignment": 12, "requires_receipt_binding": 1, "requires_unsupported_veterans_pension": 1 @@ -14290,7 +14290,7 @@ }, { "id": "qes_prefu_and_b5_ageing", - "reason": "G8-r2; QES/PREFU rows are present in the pinned artifact but unused by this residual-allocation task." + "reason": "QES/PREFU feed rows support the declared factor calculations in reference_aging.json; they never become direct calibration references or carried target values." }, { "id": "wff_tripwires", diff --git a/packages/microcosm-build/src/microcosm/build/nz/reference_profiles.json b/packages/microcosm-build/src/microcosm/build/nz/reference_profiles.json index 4fe3ebf5f4..a00eaf9637 100644 --- a/packages/microcosm-build/src/microcosm/build/nz/reference_profiles.json +++ b/packages/microcosm-build/src/microcosm/build/nz/reference_profiles.json @@ -1,5 +1,7 @@ { "schema_version": 1, + "factor_context_resource": "reference_aging.json", + "interval_resource": "reference_intervals.json", "dimensions": { "census_residual_allocation": { "default": "mar", @@ -70601,17 +70603,1475 @@ "aging_index": { "default": "central", "profiles": { - "central": { - "transformations": [], - "deferred": true - }, "low": { - "available": false, - "transformations": [] + "transformations": [ + { + "operation": "scale_money_and_intervals", + "factor_id": "ird_ty2024_to_ty2027_low", + "reference_names": [ + "ird_taxable_income_total_by_band__row_8", + "ird_taxable_income_total_by_band__row_9", + "ird_taxable_income_total_by_band__row_10", + "ird_taxable_income_total_by_band__row_11", + "ird_taxable_income_total_by_band__row_12", + "ird_taxable_income_total_by_band__row_13", + "ird_taxable_income_total_by_band__row_14", + "ird_taxable_income_total_by_band__row_15", + "ird_taxable_income_total_by_band__row_16", + "ird_taxable_income_total_by_band__row_17", + "ird_taxable_income_total_by_band__row_18", + "ird_taxable_income_total_by_band__row_19", + "ird_taxable_income_total_by_band__row_20", + "ird_taxable_income_total_by_band__row_21", + "ird_taxable_income_total_by_band__row_22", + "ird_taxable_income_total_by_band__row_23", + "ird_taxable_income_total_by_band__row_24", + "ird_taxable_income_total_by_band__row_25", + "ird_taxable_income_total_by_band__row_26", + "ird_taxable_income_total_by_band__row_27", + "ird_taxable_income_total_by_band__row_28", + "ird_taxable_income_total_by_band__row_29", + "ird_taxable_income_total_by_band__row_30", + "ird_taxable_income_total_by_band__row_31", + "ird_taxable_income_total_by_band__row_32", + "ird_taxable_income_total_by_band__row_33", + "ird_taxable_income_total_by_band__row_34", + "ird_taxable_income_total_by_band__row_35", + "ird_taxable_income_total_by_band__row_36", + "ird_taxable_income_total_by_band__row_37", + "ird_taxable_income_total_by_band__row_38", + "ird_taxable_income_total_by_band__row_39", + "ird_taxable_income_total_by_band__row_40", + "ird_taxable_income_total_by_band__row_41", + "ird_taxable_income_total_by_band__row_42", + "ird_taxable_income_total_by_band__row_43", + "ird_taxable_income_total_by_band__row_44", + "ird_taxable_income_total_by_band__row_45", + "ird_taxable_income_total_by_band__row_46", + "ird_taxable_income_total_by_band__row_47", + "ird_taxable_income_total_by_band__row_48", + "ird_taxable_income_total_by_band__row_49", + "ird_taxable_income_total_by_band__row_50", + "ird_taxable_income_total_by_band__row_51", + "ird_taxable_income_total_by_band__row_52", + "ird_taxable_income_total_by_band__row_53", + "ird_taxable_income_total_by_band__row_54", + "ird_taxable_income_total_by_band__row_55", + "ird_taxable_income_total_by_band__row_56", + "ird_taxable_income_total_by_band__row_57", + "ird_taxable_income_total_by_band__row_58", + "ird_taxable_income_total_by_band__row_59", + "ird_taxable_income_total_by_band__row_60", + "ird_taxable_income_total_by_band__row_61", + "ird_taxable_income_total_by_band__row_62", + "ird_taxable_income_total_by_band__row_63", + "ird_taxable_income_total_by_band__row_64", + "ird_taxable_income_total_by_band__row_65", + "ird_taxable_income_total_by_band__row_66", + "ird_taxable_income_total_by_band__row_67", + "ird_taxable_income_total_by_band__row_68", + "ird_taxable_income_total_by_band__row_69", + "ird_taxable_income_total_by_band__row_70", + "ird_taxable_income_total_by_band__row_71", + "ird_taxable_income_total_by_band__row_72", + "ird_taxable_income_total_by_band__row_73", + "ird_taxable_income_total_by_band__row_74", + "ird_taxable_income_total_by_band__row_75", + "ird_taxable_income_total_by_band__row_76", + "ird_taxable_income_total_by_band__row_77", + "ird_taxable_income_total_by_band__row_78", + "ird_taxable_income_total_by_band__row_79", + "ird_taxable_income_total_by_band__row_80", + "ird_taxable_income_total_by_band__row_81", + "ird_taxable_income_total_by_band__row_82", + "ird_taxable_income_total_by_band__row_83", + "ird_taxable_income_total_by_band__row_84", + "ird_taxable_income_total_by_band__row_85", + "ird_taxable_income_total_by_band__row_86", + "ird_taxable_income_total_by_band__row_87", + "ird_taxable_income_total_by_band__row_88", + "ird_taxable_income_total_by_band__row_89", + "ird_taxable_income_total_by_band__row_90", + "ird_taxable_income_total_by_band__row_91", + "ird_taxable_income_total_by_band__row_92", + "ird_taxable_income_total_by_band__row_93", + "ird_taxable_income_total_by_band__row_94", + "ird_taxable_income_total_by_band__row_95", + "ird_taxable_income_total_by_band__row_96", + "ird_taxable_income_total_by_band__row_97", + "ird_taxable_income_total_by_band__row_98", + "ird_taxable_income_total_by_band__row_99", + "ird_taxable_income_total_by_band__row_100", + "ird_taxable_income_total_by_band__row_101", + "ird_taxable_income_total_by_band__row_102", + "ird_taxable_income_total_by_band__row_103", + "ird_taxable_income_total_by_band__row_104", + "ird_taxable_income_total_by_band__row_105", + "ird_taxable_income_total_by_band__row_106", + "ird_taxable_income_total_by_band__row_107", + "ird_taxable_income_total_by_band__row_108", + "ird_taxable_income_total_by_band__row_109", + "ird_taxable_income_total_by_band__row_110", + "ird_taxable_income_total_by_band__row_111", + "ird_taxable_income_total_by_band__row_112", + "ird_taxable_income_total_by_band__row_113", + "ird_taxable_income_total_by_band__row_114", + "ird_taxable_income_total_by_band__row_115", + "ird_taxable_income_total_by_band__row_116", + "ird_taxable_income_total_by_band__row_117", + "ird_taxable_income_total_by_band__row_118", + "ird_taxable_income_total_by_band__row_119", + "ird_taxable_income_total_by_band__row_120", + "ird_taxable_income_total_by_band__row_121", + "ird_taxable_income_total_by_band__row_122", + "ird_taxable_income_total_by_band__row_123", + "ird_taxable_income_total_by_band__row_124", + "ird_taxable_income_total_by_band__row_125", + "ird_taxable_income_total_by_band__row_126", + "ird_taxable_income_total_by_band__row_127", + "ird_taxable_income_total_by_band__row_128", + "ird_taxable_income_total_by_band__row_129", + "ird_taxable_income_total_by_band__row_130", + "ird_taxable_income_total_by_band__row_131", + "ird_taxable_income_total_by_band__row_132", + "ird_taxable_income_total_by_band__row_133", + "ird_taxable_income_total_by_band__row_134", + "ird_taxable_income_total_by_band__row_135", + "ird_taxable_income_total_by_band__row_136", + "ird_taxable_income_total_by_band__row_137", + "ird_taxable_income_total_by_band__row_138", + "ird_taxable_income_total_by_band__row_139", + "ird_taxable_income_total_by_band__row_140", + "ird_taxable_income_total_by_band__row_141", + "ird_taxable_income_total_by_band__row_142", + "ird_taxable_income_total_by_band__row_143", + "ird_taxable_income_total_by_band__row_144", + "ird_taxable_income_total_by_band__row_145", + "ird_taxable_income_total_by_band__row_146", + "ird_taxable_income_total_by_band__row_147", + "ird_taxable_income_total_by_band__row_148", + "ird_taxable_income_total_by_band__row_149", + "ird_taxable_income_total_by_band__row_150", + "ird_taxable_income_total_by_band__row_151", + "ird_taxable_income_total_by_band__row_152", + "ird_taxable_income_total_by_band__row_153", + "ird_taxable_income_total_by_band__row_154", + "ird_taxable_income_total_by_band__row_155", + "ird_taxable_income_total_by_band__row_156", + "ird_taxable_income_total_by_band__row_157", + "ird_taxable_income_total_by_band__row_158", + "ird_taxable_income_total_by_band__row_159", + "ird_taxable_income_total_by_band__row_160", + "ird_taxable_income_total_by_band__row_161", + "ird_taxable_income_total_by_band__row_162", + "ird_taxable_income_total_by_band__row_163", + "ird_taxable_income_total_by_band__row_164", + "ird_taxable_income_total_by_band__row_165", + "ird_taxable_income_total_by_band__row_166", + "ird_taxable_income_total_by_band__row_167", + "ird_taxable_income_total_by_band__row_168", + "ird_taxable_income_total_by_band__row_169", + "ird_taxable_income_total_by_band__row_170", + "ird_taxable_income_total_by_band__row_171", + "ird_taxable_income_total_by_band__row_172", + "ird_taxable_income_total_by_band__row_173", + "ird_taxable_income_total_by_band__row_174", + "ird_taxable_income_total_by_band__row_175", + "ird_taxable_income_total_by_band__row_176", + "ird_taxable_income_total_by_band__row_177", + "ird_taxable_income_total_by_band__row_178", + "ird_taxable_income_total_by_band__row_179", + "ird_taxable_income_total_by_band__row_180", + "ird_taxable_income_total_by_band__row_181", + "ird_taxable_income_total_by_band__row_182", + "ird_taxable_income_total_by_band__row_183", + "ird_taxable_income_total_by_band__row_184", + "ird_taxable_income_total_by_band__row_185", + "ird_taxable_income_total_by_band__row_186", + "ird_taxable_income_total_by_band__row_187", + "ird_taxable_income_total_by_band__row_188", + "ird_taxable_income_total_by_band__row_189", + "ird_taxable_income_total_by_band__row_190", + "ird_taxable_income_total_by_band__row_191", + "ird_taxable_income_total_by_band__row_192", + "ird_taxable_income_total_by_band__row_193", + "ird_taxable_income_total_by_band__row_194", + "ird_taxable_income_total_by_band__row_195", + "ird_taxable_income_total_by_band__row_196", + "ird_taxable_income_total_by_band__row_197", + "ird_taxable_income_total_by_band__row_198", + "ird_taxable_income_total_by_band__row_199", + "ird_taxable_income_total_by_band__row_200", + "ird_taxable_income_total_by_band__row_201", + "ird_taxable_income_total_by_band__row_202", + "ird_taxable_income_total_by_band__row_203", + "ird_taxable_income_total_by_band__row_204", + "ird_taxable_income_total_by_band__row_205", + "ird_taxable_income_total_by_band__row_206", + "ird_taxable_income_total_by_band__row_207", + "ird_taxable_income_total_by_band__row_208", + "ird_taxable_income_total_by_band__row_209", + "ird_taxable_income_total_by_band__row_210", + "ird_taxable_income_total_by_band__row_211", + "ird_taxable_income_total_by_band__row_212", + "ird_taxable_income_total_by_band__row_213", + "ird_taxable_income_total_by_band__row_214", + "ird_taxable_income_total_by_band__row_215", + "ird_taxable_income_total_by_band__row_216", + "ird_taxable_income_total_by_band__row_217", + "ird_taxable_income_total_by_band__row_218", + "ird_taxable_income_total_by_band__row_219", + "ird_taxable_income_total_by_band__row_220", + "ird_taxable_income_total_by_band__row_221", + "ird_taxable_income_total_by_band__row_222", + "ird_taxable_income_total_by_band__row_223", + "ird_taxable_income_total_by_band__row_224", + "ird_taxable_income_total_by_band__row_225", + "ird_taxable_income_total_by_band__row_226", + "ird_taxable_income_total_by_band__row_227", + "ird_taxable_income_total_by_band__row_228", + "ird_taxable_income_total_by_band__row_229", + "ird_taxable_income_total_by_band__row_230", + "ird_taxable_income_total_by_band__row_231", + "ird_taxable_income_total_by_band__row_232", + "ird_taxable_income_total_by_band__row_233", + "ird_taxable_income_total_by_band__row_234", + "ird_taxable_income_total_by_band__row_235", + "ird_taxable_income_total_by_band__row_236", + "ird_taxable_income_total_by_band__row_237", + "ird_taxable_income_total_by_band__row_238", + "ird_taxable_income_total_by_band__row_239", + "ird_taxable_income_total_by_band__row_240", + "ird_taxable_income_total_by_band__row_241", + "ird_taxable_income_total_by_band__row_242", + "ird_taxable_income_total_by_band__row_243", + "ird_taxable_income_total_by_band__row_244" + ], + "count_reference_names": [ + "ird_taxable_income_people_by_band__row_8", + "ird_taxable_income_people_by_band__row_9", + "ird_taxable_income_people_by_band__row_10", + "ird_taxable_income_people_by_band__row_11", + "ird_taxable_income_people_by_band__row_12", + "ird_taxable_income_people_by_band__row_13", + "ird_taxable_income_people_by_band__row_14", + "ird_taxable_income_people_by_band__row_15", + "ird_taxable_income_people_by_band__row_16", + "ird_taxable_income_people_by_band__row_17", + "ird_taxable_income_people_by_band__row_18", + "ird_taxable_income_people_by_band__row_19", + "ird_taxable_income_people_by_band__row_20", + "ird_taxable_income_people_by_band__row_21", + "ird_taxable_income_people_by_band__row_22", + "ird_taxable_income_people_by_band__row_23", + "ird_taxable_income_people_by_band__row_24", + "ird_taxable_income_people_by_band__row_25", + "ird_taxable_income_people_by_band__row_26", + "ird_taxable_income_people_by_band__row_27", + "ird_taxable_income_people_by_band__row_28", + "ird_taxable_income_people_by_band__row_29", + "ird_taxable_income_people_by_band__row_30", + "ird_taxable_income_people_by_band__row_31", + "ird_taxable_income_people_by_band__row_32", + "ird_taxable_income_people_by_band__row_33", + "ird_taxable_income_people_by_band__row_34", + "ird_taxable_income_people_by_band__row_35", + "ird_taxable_income_people_by_band__row_36", + "ird_taxable_income_people_by_band__row_37", + "ird_taxable_income_people_by_band__row_38", + "ird_taxable_income_people_by_band__row_39", + "ird_taxable_income_people_by_band__row_40", + "ird_taxable_income_people_by_band__row_41", + "ird_taxable_income_people_by_band__row_42", + "ird_taxable_income_people_by_band__row_43", + "ird_taxable_income_people_by_band__row_44", + "ird_taxable_income_people_by_band__row_45", + "ird_taxable_income_people_by_band__row_46", + "ird_taxable_income_people_by_band__row_47", + "ird_taxable_income_people_by_band__row_48", + "ird_taxable_income_people_by_band__row_49", + "ird_taxable_income_people_by_band__row_50", + "ird_taxable_income_people_by_band__row_51", + "ird_taxable_income_people_by_band__row_52", + "ird_taxable_income_people_by_band__row_53", + "ird_taxable_income_people_by_band__row_54", + "ird_taxable_income_people_by_band__row_55", + "ird_taxable_income_people_by_band__row_56", + "ird_taxable_income_people_by_band__row_57", + "ird_taxable_income_people_by_band__row_58", + "ird_taxable_income_people_by_band__row_59", + "ird_taxable_income_people_by_band__row_60", + "ird_taxable_income_people_by_band__row_61", + "ird_taxable_income_people_by_band__row_62", + "ird_taxable_income_people_by_band__row_63", + "ird_taxable_income_people_by_band__row_64", + "ird_taxable_income_people_by_band__row_65", + "ird_taxable_income_people_by_band__row_66", + "ird_taxable_income_people_by_band__row_67", + "ird_taxable_income_people_by_band__row_68", + "ird_taxable_income_people_by_band__row_69", + "ird_taxable_income_people_by_band__row_70", + "ird_taxable_income_people_by_band__row_71", + "ird_taxable_income_people_by_band__row_72", + "ird_taxable_income_people_by_band__row_73", + "ird_taxable_income_people_by_band__row_74", + "ird_taxable_income_people_by_band__row_75", + "ird_taxable_income_people_by_band__row_76", + "ird_taxable_income_people_by_band__row_77", + "ird_taxable_income_people_by_band__row_78", + "ird_taxable_income_people_by_band__row_79", + "ird_taxable_income_people_by_band__row_80", + "ird_taxable_income_people_by_band__row_81", + "ird_taxable_income_people_by_band__row_82", + "ird_taxable_income_people_by_band__row_83", + "ird_taxable_income_people_by_band__row_84", + "ird_taxable_income_people_by_band__row_85", + "ird_taxable_income_people_by_band__row_86", + "ird_taxable_income_people_by_band__row_87", + "ird_taxable_income_people_by_band__row_88", + "ird_taxable_income_people_by_band__row_89", + "ird_taxable_income_people_by_band__row_90", + "ird_taxable_income_people_by_band__row_91", + "ird_taxable_income_people_by_band__row_92", + "ird_taxable_income_people_by_band__row_93", + "ird_taxable_income_people_by_band__row_94", + "ird_taxable_income_people_by_band__row_95", + "ird_taxable_income_people_by_band__row_96", + "ird_taxable_income_people_by_band__row_97", + "ird_taxable_income_people_by_band__row_98", + "ird_taxable_income_people_by_band__row_99", + "ird_taxable_income_people_by_band__row_100", + "ird_taxable_income_people_by_band__row_101", + "ird_taxable_income_people_by_band__row_102", + "ird_taxable_income_people_by_band__row_103", + "ird_taxable_income_people_by_band__row_104", + "ird_taxable_income_people_by_band__row_105", + "ird_taxable_income_people_by_band__row_106", + "ird_taxable_income_people_by_band__row_107", + "ird_taxable_income_people_by_band__row_108", + "ird_taxable_income_people_by_band__row_109", + "ird_taxable_income_people_by_band__row_110", + "ird_taxable_income_people_by_band__row_111", + "ird_taxable_income_people_by_band__row_112", + "ird_taxable_income_people_by_band__row_113", + "ird_taxable_income_people_by_band__row_114", + "ird_taxable_income_people_by_band__row_115", + "ird_taxable_income_people_by_band__row_116", + "ird_taxable_income_people_by_band__row_117", + "ird_taxable_income_people_by_band__row_118", + "ird_taxable_income_people_by_band__row_119", + "ird_taxable_income_people_by_band__row_120", + "ird_taxable_income_people_by_band__row_121", + "ird_taxable_income_people_by_band__row_122", + "ird_taxable_income_people_by_band__row_123", + "ird_taxable_income_people_by_band__row_124", + "ird_taxable_income_people_by_band__row_125", + "ird_taxable_income_people_by_band__row_126", + "ird_taxable_income_people_by_band__row_127", + "ird_taxable_income_people_by_band__row_128", + "ird_taxable_income_people_by_band__row_129", + "ird_taxable_income_people_by_band__row_130", + "ird_taxable_income_people_by_band__row_131", + "ird_taxable_income_people_by_band__row_132", + "ird_taxable_income_people_by_band__row_133", + "ird_taxable_income_people_by_band__row_134", + "ird_taxable_income_people_by_band__row_135", + "ird_taxable_income_people_by_band__row_136", + "ird_taxable_income_people_by_band__row_137", + "ird_taxable_income_people_by_band__row_138", + "ird_taxable_income_people_by_band__row_139", + "ird_taxable_income_people_by_band__row_140", + "ird_taxable_income_people_by_band__row_141", + "ird_taxable_income_people_by_band__row_142", + "ird_taxable_income_people_by_band__row_143", + "ird_taxable_income_people_by_band__row_144", + "ird_taxable_income_people_by_band__row_145", + "ird_taxable_income_people_by_band__row_146", + "ird_taxable_income_people_by_band__row_147", + "ird_taxable_income_people_by_band__row_148", + "ird_taxable_income_people_by_band__row_149", + "ird_taxable_income_people_by_band__row_150", + "ird_taxable_income_people_by_band__row_151", + "ird_taxable_income_people_by_band__row_152", + "ird_taxable_income_people_by_band__row_153", + "ird_taxable_income_people_by_band__row_154", + "ird_taxable_income_people_by_band__row_155", + "ird_taxable_income_people_by_band__row_156", + "ird_taxable_income_people_by_band__row_157", + "ird_taxable_income_people_by_band__row_158", + "ird_taxable_income_people_by_band__row_159", + "ird_taxable_income_people_by_band__row_160", + "ird_taxable_income_people_by_band__row_161", + "ird_taxable_income_people_by_band__row_162", + "ird_taxable_income_people_by_band__row_163", + "ird_taxable_income_people_by_band__row_164", + "ird_taxable_income_people_by_band__row_165", + "ird_taxable_income_people_by_band__row_166", + "ird_taxable_income_people_by_band__row_167", + "ird_taxable_income_people_by_band__row_168", + "ird_taxable_income_people_by_band__row_169", + "ird_taxable_income_people_by_band__row_170", + "ird_taxable_income_people_by_band__row_171", + "ird_taxable_income_people_by_band__row_172", + "ird_taxable_income_people_by_band__row_173", + "ird_taxable_income_people_by_band__row_174", + "ird_taxable_income_people_by_band__row_175", + "ird_taxable_income_people_by_band__row_176", + "ird_taxable_income_people_by_band__row_177", + "ird_taxable_income_people_by_band__row_178", + "ird_taxable_income_people_by_band__row_179", + "ird_taxable_income_people_by_band__row_180", + "ird_taxable_income_people_by_band__row_181", + "ird_taxable_income_people_by_band__row_182", + "ird_taxable_income_people_by_band__row_183", + "ird_taxable_income_people_by_band__row_184", + "ird_taxable_income_people_by_band__row_185", + "ird_taxable_income_people_by_band__row_186", + "ird_taxable_income_people_by_band__row_187", + "ird_taxable_income_people_by_band__row_188", + "ird_taxable_income_people_by_band__row_189", + "ird_taxable_income_people_by_band__row_190", + "ird_taxable_income_people_by_band__row_191", + "ird_taxable_income_people_by_band__row_192", + "ird_taxable_income_people_by_band__row_193", + "ird_taxable_income_people_by_band__row_194", + "ird_taxable_income_people_by_band__row_195", + "ird_taxable_income_people_by_band__row_196", + "ird_taxable_income_people_by_band__row_197", + "ird_taxable_income_people_by_band__row_198", + "ird_taxable_income_people_by_band__row_199", + "ird_taxable_income_people_by_band__row_200", + "ird_taxable_income_people_by_band__row_201", + "ird_taxable_income_people_by_band__row_202", + "ird_taxable_income_people_by_band__row_203", + "ird_taxable_income_people_by_band__row_204", + "ird_taxable_income_people_by_band__row_205", + "ird_taxable_income_people_by_band__row_206", + "ird_taxable_income_people_by_band__row_207", + "ird_taxable_income_people_by_band__row_208", + "ird_taxable_income_people_by_band__row_209", + "ird_taxable_income_people_by_band__row_210", + "ird_taxable_income_people_by_band__row_211", + "ird_taxable_income_people_by_band__row_212", + "ird_taxable_income_people_by_band__row_213", + "ird_taxable_income_people_by_band__row_214", + "ird_taxable_income_people_by_band__row_215", + "ird_taxable_income_people_by_band__row_216", + "ird_taxable_income_people_by_band__row_217", + "ird_taxable_income_people_by_band__row_218", + "ird_taxable_income_people_by_band__row_219", + "ird_taxable_income_people_by_band__row_220", + "ird_taxable_income_people_by_band__row_221", + "ird_taxable_income_people_by_band__row_222", + "ird_taxable_income_people_by_band__row_223", + "ird_taxable_income_people_by_band__row_224", + "ird_taxable_income_people_by_band__row_225", + "ird_taxable_income_people_by_band__row_226", + "ird_taxable_income_people_by_band__row_227", + "ird_taxable_income_people_by_band__row_228", + "ird_taxable_income_people_by_band__row_229", + "ird_taxable_income_people_by_band__row_230", + "ird_taxable_income_people_by_band__row_231", + "ird_taxable_income_people_by_band__row_232", + "ird_taxable_income_people_by_band__row_233", + "ird_taxable_income_people_by_band__row_234", + "ird_taxable_income_people_by_band__row_235", + "ird_taxable_income_people_by_band__row_236", + "ird_taxable_income_people_by_band__row_237", + "ird_taxable_income_people_by_band__row_238", + "ird_taxable_income_people_by_band__row_239", + "ird_taxable_income_people_by_band__row_240", + "ird_taxable_income_people_by_band__row_241", + "ird_taxable_income_people_by_band__row_242", + "ird_taxable_income_people_by_band__row_243", + "ird_taxable_income_people_by_band__row_244" + ], + "interval_table_ids": [ + "ird_taxable_income_national_ty2024" + ], + "required_measurement_binding": "ird_taxable_income_ty2027_v1" + } + ] + }, + "central": { + "transformations": [ + { + "operation": "scale_money_and_intervals", + "factor_id": "ird_ty2024_to_ty2027_central", + "reference_names": [ + "ird_taxable_income_total_by_band__row_8", + "ird_taxable_income_total_by_band__row_9", + "ird_taxable_income_total_by_band__row_10", + "ird_taxable_income_total_by_band__row_11", + "ird_taxable_income_total_by_band__row_12", + "ird_taxable_income_total_by_band__row_13", + "ird_taxable_income_total_by_band__row_14", + "ird_taxable_income_total_by_band__row_15", + "ird_taxable_income_total_by_band__row_16", + "ird_taxable_income_total_by_band__row_17", + "ird_taxable_income_total_by_band__row_18", + "ird_taxable_income_total_by_band__row_19", + "ird_taxable_income_total_by_band__row_20", + "ird_taxable_income_total_by_band__row_21", + "ird_taxable_income_total_by_band__row_22", + "ird_taxable_income_total_by_band__row_23", + "ird_taxable_income_total_by_band__row_24", + "ird_taxable_income_total_by_band__row_25", + "ird_taxable_income_total_by_band__row_26", + "ird_taxable_income_total_by_band__row_27", + "ird_taxable_income_total_by_band__row_28", + "ird_taxable_income_total_by_band__row_29", + "ird_taxable_income_total_by_band__row_30", + "ird_taxable_income_total_by_band__row_31", + "ird_taxable_income_total_by_band__row_32", + "ird_taxable_income_total_by_band__row_33", + "ird_taxable_income_total_by_band__row_34", + "ird_taxable_income_total_by_band__row_35", + "ird_taxable_income_total_by_band__row_36", + "ird_taxable_income_total_by_band__row_37", + "ird_taxable_income_total_by_band__row_38", + "ird_taxable_income_total_by_band__row_39", + "ird_taxable_income_total_by_band__row_40", + "ird_taxable_income_total_by_band__row_41", + "ird_taxable_income_total_by_band__row_42", + "ird_taxable_income_total_by_band__row_43", + "ird_taxable_income_total_by_band__row_44", + "ird_taxable_income_total_by_band__row_45", + "ird_taxable_income_total_by_band__row_46", + "ird_taxable_income_total_by_band__row_47", + "ird_taxable_income_total_by_band__row_48", + "ird_taxable_income_total_by_band__row_49", + "ird_taxable_income_total_by_band__row_50", + "ird_taxable_income_total_by_band__row_51", + "ird_taxable_income_total_by_band__row_52", + "ird_taxable_income_total_by_band__row_53", + "ird_taxable_income_total_by_band__row_54", + "ird_taxable_income_total_by_band__row_55", + "ird_taxable_income_total_by_band__row_56", + "ird_taxable_income_total_by_band__row_57", + "ird_taxable_income_total_by_band__row_58", + "ird_taxable_income_total_by_band__row_59", + "ird_taxable_income_total_by_band__row_60", + "ird_taxable_income_total_by_band__row_61", + "ird_taxable_income_total_by_band__row_62", + "ird_taxable_income_total_by_band__row_63", + "ird_taxable_income_total_by_band__row_64", + "ird_taxable_income_total_by_band__row_65", + "ird_taxable_income_total_by_band__row_66", + "ird_taxable_income_total_by_band__row_67", + "ird_taxable_income_total_by_band__row_68", + "ird_taxable_income_total_by_band__row_69", + "ird_taxable_income_total_by_band__row_70", + "ird_taxable_income_total_by_band__row_71", + "ird_taxable_income_total_by_band__row_72", + "ird_taxable_income_total_by_band__row_73", + "ird_taxable_income_total_by_band__row_74", + "ird_taxable_income_total_by_band__row_75", + "ird_taxable_income_total_by_band__row_76", + "ird_taxable_income_total_by_band__row_77", + "ird_taxable_income_total_by_band__row_78", + "ird_taxable_income_total_by_band__row_79", + "ird_taxable_income_total_by_band__row_80", + "ird_taxable_income_total_by_band__row_81", + "ird_taxable_income_total_by_band__row_82", + "ird_taxable_income_total_by_band__row_83", + "ird_taxable_income_total_by_band__row_84", + "ird_taxable_income_total_by_band__row_85", + "ird_taxable_income_total_by_band__row_86", + "ird_taxable_income_total_by_band__row_87", + "ird_taxable_income_total_by_band__row_88", + "ird_taxable_income_total_by_band__row_89", + "ird_taxable_income_total_by_band__row_90", + "ird_taxable_income_total_by_band__row_91", + "ird_taxable_income_total_by_band__row_92", + "ird_taxable_income_total_by_band__row_93", + "ird_taxable_income_total_by_band__row_94", + "ird_taxable_income_total_by_band__row_95", + "ird_taxable_income_total_by_band__row_96", + "ird_taxable_income_total_by_band__row_97", + "ird_taxable_income_total_by_band__row_98", + "ird_taxable_income_total_by_band__row_99", + "ird_taxable_income_total_by_band__row_100", + "ird_taxable_income_total_by_band__row_101", + "ird_taxable_income_total_by_band__row_102", + "ird_taxable_income_total_by_band__row_103", + "ird_taxable_income_total_by_band__row_104", + "ird_taxable_income_total_by_band__row_105", + "ird_taxable_income_total_by_band__row_106", + "ird_taxable_income_total_by_band__row_107", + "ird_taxable_income_total_by_band__row_108", + "ird_taxable_income_total_by_band__row_109", + "ird_taxable_income_total_by_band__row_110", + "ird_taxable_income_total_by_band__row_111", + "ird_taxable_income_total_by_band__row_112", + "ird_taxable_income_total_by_band__row_113", + "ird_taxable_income_total_by_band__row_114", + "ird_taxable_income_total_by_band__row_115", + "ird_taxable_income_total_by_band__row_116", + "ird_taxable_income_total_by_band__row_117", + "ird_taxable_income_total_by_band__row_118", + "ird_taxable_income_total_by_band__row_119", + "ird_taxable_income_total_by_band__row_120", + "ird_taxable_income_total_by_band__row_121", + "ird_taxable_income_total_by_band__row_122", + "ird_taxable_income_total_by_band__row_123", + "ird_taxable_income_total_by_band__row_124", + "ird_taxable_income_total_by_band__row_125", + "ird_taxable_income_total_by_band__row_126", + "ird_taxable_income_total_by_band__row_127", + "ird_taxable_income_total_by_band__row_128", + "ird_taxable_income_total_by_band__row_129", + "ird_taxable_income_total_by_band__row_130", + "ird_taxable_income_total_by_band__row_131", + "ird_taxable_income_total_by_band__row_132", + "ird_taxable_income_total_by_band__row_133", + "ird_taxable_income_total_by_band__row_134", + "ird_taxable_income_total_by_band__row_135", + "ird_taxable_income_total_by_band__row_136", + "ird_taxable_income_total_by_band__row_137", + "ird_taxable_income_total_by_band__row_138", + "ird_taxable_income_total_by_band__row_139", + "ird_taxable_income_total_by_band__row_140", + "ird_taxable_income_total_by_band__row_141", + "ird_taxable_income_total_by_band__row_142", + "ird_taxable_income_total_by_band__row_143", + "ird_taxable_income_total_by_band__row_144", + "ird_taxable_income_total_by_band__row_145", + "ird_taxable_income_total_by_band__row_146", + "ird_taxable_income_total_by_band__row_147", + "ird_taxable_income_total_by_band__row_148", + "ird_taxable_income_total_by_band__row_149", + "ird_taxable_income_total_by_band__row_150", + "ird_taxable_income_total_by_band__row_151", + "ird_taxable_income_total_by_band__row_152", + "ird_taxable_income_total_by_band__row_153", + "ird_taxable_income_total_by_band__row_154", + "ird_taxable_income_total_by_band__row_155", + "ird_taxable_income_total_by_band__row_156", + "ird_taxable_income_total_by_band__row_157", + "ird_taxable_income_total_by_band__row_158", + "ird_taxable_income_total_by_band__row_159", + "ird_taxable_income_total_by_band__row_160", + "ird_taxable_income_total_by_band__row_161", + "ird_taxable_income_total_by_band__row_162", + "ird_taxable_income_total_by_band__row_163", + "ird_taxable_income_total_by_band__row_164", + "ird_taxable_income_total_by_band__row_165", + "ird_taxable_income_total_by_band__row_166", + "ird_taxable_income_total_by_band__row_167", + "ird_taxable_income_total_by_band__row_168", + "ird_taxable_income_total_by_band__row_169", + "ird_taxable_income_total_by_band__row_170", + "ird_taxable_income_total_by_band__row_171", + "ird_taxable_income_total_by_band__row_172", + "ird_taxable_income_total_by_band__row_173", + "ird_taxable_income_total_by_band__row_174", + "ird_taxable_income_total_by_band__row_175", + "ird_taxable_income_total_by_band__row_176", + "ird_taxable_income_total_by_band__row_177", + "ird_taxable_income_total_by_band__row_178", + "ird_taxable_income_total_by_band__row_179", + "ird_taxable_income_total_by_band__row_180", + "ird_taxable_income_total_by_band__row_181", + "ird_taxable_income_total_by_band__row_182", + "ird_taxable_income_total_by_band__row_183", + "ird_taxable_income_total_by_band__row_184", + "ird_taxable_income_total_by_band__row_185", + "ird_taxable_income_total_by_band__row_186", + "ird_taxable_income_total_by_band__row_187", + "ird_taxable_income_total_by_band__row_188", + "ird_taxable_income_total_by_band__row_189", + "ird_taxable_income_total_by_band__row_190", + "ird_taxable_income_total_by_band__row_191", + "ird_taxable_income_total_by_band__row_192", + "ird_taxable_income_total_by_band__row_193", + "ird_taxable_income_total_by_band__row_194", + "ird_taxable_income_total_by_band__row_195", + "ird_taxable_income_total_by_band__row_196", + "ird_taxable_income_total_by_band__row_197", + "ird_taxable_income_total_by_band__row_198", + "ird_taxable_income_total_by_band__row_199", + "ird_taxable_income_total_by_band__row_200", + "ird_taxable_income_total_by_band__row_201", + "ird_taxable_income_total_by_band__row_202", + "ird_taxable_income_total_by_band__row_203", + "ird_taxable_income_total_by_band__row_204", + "ird_taxable_income_total_by_band__row_205", + "ird_taxable_income_total_by_band__row_206", + "ird_taxable_income_total_by_band__row_207", + "ird_taxable_income_total_by_band__row_208", + "ird_taxable_income_total_by_band__row_209", + "ird_taxable_income_total_by_band__row_210", + "ird_taxable_income_total_by_band__row_211", + "ird_taxable_income_total_by_band__row_212", + "ird_taxable_income_total_by_band__row_213", + "ird_taxable_income_total_by_band__row_214", + "ird_taxable_income_total_by_band__row_215", + "ird_taxable_income_total_by_band__row_216", + "ird_taxable_income_total_by_band__row_217", + "ird_taxable_income_total_by_band__row_218", + "ird_taxable_income_total_by_band__row_219", + "ird_taxable_income_total_by_band__row_220", + "ird_taxable_income_total_by_band__row_221", + "ird_taxable_income_total_by_band__row_222", + "ird_taxable_income_total_by_band__row_223", + "ird_taxable_income_total_by_band__row_224", + "ird_taxable_income_total_by_band__row_225", + "ird_taxable_income_total_by_band__row_226", + "ird_taxable_income_total_by_band__row_227", + "ird_taxable_income_total_by_band__row_228", + "ird_taxable_income_total_by_band__row_229", + "ird_taxable_income_total_by_band__row_230", + "ird_taxable_income_total_by_band__row_231", + "ird_taxable_income_total_by_band__row_232", + "ird_taxable_income_total_by_band__row_233", + "ird_taxable_income_total_by_band__row_234", + "ird_taxable_income_total_by_band__row_235", + "ird_taxable_income_total_by_band__row_236", + "ird_taxable_income_total_by_band__row_237", + "ird_taxable_income_total_by_band__row_238", + "ird_taxable_income_total_by_band__row_239", + "ird_taxable_income_total_by_band__row_240", + "ird_taxable_income_total_by_band__row_241", + "ird_taxable_income_total_by_band__row_242", + "ird_taxable_income_total_by_band__row_243", + "ird_taxable_income_total_by_band__row_244" + ], + "count_reference_names": [ + "ird_taxable_income_people_by_band__row_8", + "ird_taxable_income_people_by_band__row_9", + "ird_taxable_income_people_by_band__row_10", + "ird_taxable_income_people_by_band__row_11", + "ird_taxable_income_people_by_band__row_12", + "ird_taxable_income_people_by_band__row_13", + "ird_taxable_income_people_by_band__row_14", + "ird_taxable_income_people_by_band__row_15", + "ird_taxable_income_people_by_band__row_16", + "ird_taxable_income_people_by_band__row_17", + "ird_taxable_income_people_by_band__row_18", + "ird_taxable_income_people_by_band__row_19", + "ird_taxable_income_people_by_band__row_20", + "ird_taxable_income_people_by_band__row_21", + "ird_taxable_income_people_by_band__row_22", + "ird_taxable_income_people_by_band__row_23", + "ird_taxable_income_people_by_band__row_24", + "ird_taxable_income_people_by_band__row_25", + "ird_taxable_income_people_by_band__row_26", + "ird_taxable_income_people_by_band__row_27", + "ird_taxable_income_people_by_band__row_28", + "ird_taxable_income_people_by_band__row_29", + "ird_taxable_income_people_by_band__row_30", + "ird_taxable_income_people_by_band__row_31", + "ird_taxable_income_people_by_band__row_32", + "ird_taxable_income_people_by_band__row_33", + "ird_taxable_income_people_by_band__row_34", + "ird_taxable_income_people_by_band__row_35", + "ird_taxable_income_people_by_band__row_36", + "ird_taxable_income_people_by_band__row_37", + "ird_taxable_income_people_by_band__row_38", + "ird_taxable_income_people_by_band__row_39", + "ird_taxable_income_people_by_band__row_40", + "ird_taxable_income_people_by_band__row_41", + "ird_taxable_income_people_by_band__row_42", + "ird_taxable_income_people_by_band__row_43", + "ird_taxable_income_people_by_band__row_44", + "ird_taxable_income_people_by_band__row_45", + "ird_taxable_income_people_by_band__row_46", + "ird_taxable_income_people_by_band__row_47", + "ird_taxable_income_people_by_band__row_48", + "ird_taxable_income_people_by_band__row_49", + "ird_taxable_income_people_by_band__row_50", + "ird_taxable_income_people_by_band__row_51", + "ird_taxable_income_people_by_band__row_52", + "ird_taxable_income_people_by_band__row_53", + "ird_taxable_income_people_by_band__row_54", + "ird_taxable_income_people_by_band__row_55", + "ird_taxable_income_people_by_band__row_56", + "ird_taxable_income_people_by_band__row_57", + "ird_taxable_income_people_by_band__row_58", + "ird_taxable_income_people_by_band__row_59", + "ird_taxable_income_people_by_band__row_60", + "ird_taxable_income_people_by_band__row_61", + "ird_taxable_income_people_by_band__row_62", + "ird_taxable_income_people_by_band__row_63", + "ird_taxable_income_people_by_band__row_64", + "ird_taxable_income_people_by_band__row_65", + "ird_taxable_income_people_by_band__row_66", + "ird_taxable_income_people_by_band__row_67", + "ird_taxable_income_people_by_band__row_68", + "ird_taxable_income_people_by_band__row_69", + "ird_taxable_income_people_by_band__row_70", + "ird_taxable_income_people_by_band__row_71", + "ird_taxable_income_people_by_band__row_72", + "ird_taxable_income_people_by_band__row_73", + "ird_taxable_income_people_by_band__row_74", + "ird_taxable_income_people_by_band__row_75", + "ird_taxable_income_people_by_band__row_76", + "ird_taxable_income_people_by_band__row_77", + "ird_taxable_income_people_by_band__row_78", + "ird_taxable_income_people_by_band__row_79", + "ird_taxable_income_people_by_band__row_80", + "ird_taxable_income_people_by_band__row_81", + "ird_taxable_income_people_by_band__row_82", + "ird_taxable_income_people_by_band__row_83", + "ird_taxable_income_people_by_band__row_84", + "ird_taxable_income_people_by_band__row_85", + "ird_taxable_income_people_by_band__row_86", + "ird_taxable_income_people_by_band__row_87", + "ird_taxable_income_people_by_band__row_88", + "ird_taxable_income_people_by_band__row_89", + "ird_taxable_income_people_by_band__row_90", + "ird_taxable_income_people_by_band__row_91", + "ird_taxable_income_people_by_band__row_92", + "ird_taxable_income_people_by_band__row_93", + "ird_taxable_income_people_by_band__row_94", + "ird_taxable_income_people_by_band__row_95", + "ird_taxable_income_people_by_band__row_96", + "ird_taxable_income_people_by_band__row_97", + "ird_taxable_income_people_by_band__row_98", + "ird_taxable_income_people_by_band__row_99", + "ird_taxable_income_people_by_band__row_100", + "ird_taxable_income_people_by_band__row_101", + "ird_taxable_income_people_by_band__row_102", + "ird_taxable_income_people_by_band__row_103", + "ird_taxable_income_people_by_band__row_104", + "ird_taxable_income_people_by_band__row_105", + "ird_taxable_income_people_by_band__row_106", + "ird_taxable_income_people_by_band__row_107", + "ird_taxable_income_people_by_band__row_108", + "ird_taxable_income_people_by_band__row_109", + "ird_taxable_income_people_by_band__row_110", + "ird_taxable_income_people_by_band__row_111", + "ird_taxable_income_people_by_band__row_112", + "ird_taxable_income_people_by_band__row_113", + "ird_taxable_income_people_by_band__row_114", + "ird_taxable_income_people_by_band__row_115", + "ird_taxable_income_people_by_band__row_116", + "ird_taxable_income_people_by_band__row_117", + "ird_taxable_income_people_by_band__row_118", + "ird_taxable_income_people_by_band__row_119", + "ird_taxable_income_people_by_band__row_120", + "ird_taxable_income_people_by_band__row_121", + "ird_taxable_income_people_by_band__row_122", + "ird_taxable_income_people_by_band__row_123", + "ird_taxable_income_people_by_band__row_124", + "ird_taxable_income_people_by_band__row_125", + "ird_taxable_income_people_by_band__row_126", + "ird_taxable_income_people_by_band__row_127", + "ird_taxable_income_people_by_band__row_128", + "ird_taxable_income_people_by_band__row_129", + "ird_taxable_income_people_by_band__row_130", + "ird_taxable_income_people_by_band__row_131", + "ird_taxable_income_people_by_band__row_132", + "ird_taxable_income_people_by_band__row_133", + "ird_taxable_income_people_by_band__row_134", + "ird_taxable_income_people_by_band__row_135", + "ird_taxable_income_people_by_band__row_136", + "ird_taxable_income_people_by_band__row_137", + "ird_taxable_income_people_by_band__row_138", + "ird_taxable_income_people_by_band__row_139", + "ird_taxable_income_people_by_band__row_140", + "ird_taxable_income_people_by_band__row_141", + "ird_taxable_income_people_by_band__row_142", + "ird_taxable_income_people_by_band__row_143", + "ird_taxable_income_people_by_band__row_144", + "ird_taxable_income_people_by_band__row_145", + "ird_taxable_income_people_by_band__row_146", + "ird_taxable_income_people_by_band__row_147", + "ird_taxable_income_people_by_band__row_148", + "ird_taxable_income_people_by_band__row_149", + "ird_taxable_income_people_by_band__row_150", + "ird_taxable_income_people_by_band__row_151", + "ird_taxable_income_people_by_band__row_152", + "ird_taxable_income_people_by_band__row_153", + "ird_taxable_income_people_by_band__row_154", + "ird_taxable_income_people_by_band__row_155", + "ird_taxable_income_people_by_band__row_156", + "ird_taxable_income_people_by_band__row_157", + "ird_taxable_income_people_by_band__row_158", + "ird_taxable_income_people_by_band__row_159", + "ird_taxable_income_people_by_band__row_160", + "ird_taxable_income_people_by_band__row_161", + "ird_taxable_income_people_by_band__row_162", + "ird_taxable_income_people_by_band__row_163", + "ird_taxable_income_people_by_band__row_164", + "ird_taxable_income_people_by_band__row_165", + "ird_taxable_income_people_by_band__row_166", + "ird_taxable_income_people_by_band__row_167", + "ird_taxable_income_people_by_band__row_168", + "ird_taxable_income_people_by_band__row_169", + "ird_taxable_income_people_by_band__row_170", + "ird_taxable_income_people_by_band__row_171", + "ird_taxable_income_people_by_band__row_172", + "ird_taxable_income_people_by_band__row_173", + "ird_taxable_income_people_by_band__row_174", + "ird_taxable_income_people_by_band__row_175", + "ird_taxable_income_people_by_band__row_176", + "ird_taxable_income_people_by_band__row_177", + "ird_taxable_income_people_by_band__row_178", + "ird_taxable_income_people_by_band__row_179", + "ird_taxable_income_people_by_band__row_180", + "ird_taxable_income_people_by_band__row_181", + "ird_taxable_income_people_by_band__row_182", + "ird_taxable_income_people_by_band__row_183", + "ird_taxable_income_people_by_band__row_184", + "ird_taxable_income_people_by_band__row_185", + "ird_taxable_income_people_by_band__row_186", + "ird_taxable_income_people_by_band__row_187", + "ird_taxable_income_people_by_band__row_188", + "ird_taxable_income_people_by_band__row_189", + "ird_taxable_income_people_by_band__row_190", + "ird_taxable_income_people_by_band__row_191", + "ird_taxable_income_people_by_band__row_192", + "ird_taxable_income_people_by_band__row_193", + "ird_taxable_income_people_by_band__row_194", + "ird_taxable_income_people_by_band__row_195", + "ird_taxable_income_people_by_band__row_196", + "ird_taxable_income_people_by_band__row_197", + "ird_taxable_income_people_by_band__row_198", + "ird_taxable_income_people_by_band__row_199", + "ird_taxable_income_people_by_band__row_200", + "ird_taxable_income_people_by_band__row_201", + "ird_taxable_income_people_by_band__row_202", + "ird_taxable_income_people_by_band__row_203", + "ird_taxable_income_people_by_band__row_204", + "ird_taxable_income_people_by_band__row_205", + "ird_taxable_income_people_by_band__row_206", + "ird_taxable_income_people_by_band__row_207", + "ird_taxable_income_people_by_band__row_208", + "ird_taxable_income_people_by_band__row_209", + "ird_taxable_income_people_by_band__row_210", + "ird_taxable_income_people_by_band__row_211", + "ird_taxable_income_people_by_band__row_212", + "ird_taxable_income_people_by_band__row_213", + "ird_taxable_income_people_by_band__row_214", + "ird_taxable_income_people_by_band__row_215", + "ird_taxable_income_people_by_band__row_216", + "ird_taxable_income_people_by_band__row_217", + "ird_taxable_income_people_by_band__row_218", + "ird_taxable_income_people_by_band__row_219", + "ird_taxable_income_people_by_band__row_220", + "ird_taxable_income_people_by_band__row_221", + "ird_taxable_income_people_by_band__row_222", + "ird_taxable_income_people_by_band__row_223", + "ird_taxable_income_people_by_band__row_224", + "ird_taxable_income_people_by_band__row_225", + "ird_taxable_income_people_by_band__row_226", + "ird_taxable_income_people_by_band__row_227", + "ird_taxable_income_people_by_band__row_228", + "ird_taxable_income_people_by_band__row_229", + "ird_taxable_income_people_by_band__row_230", + "ird_taxable_income_people_by_band__row_231", + "ird_taxable_income_people_by_band__row_232", + "ird_taxable_income_people_by_band__row_233", + "ird_taxable_income_people_by_band__row_234", + "ird_taxable_income_people_by_band__row_235", + "ird_taxable_income_people_by_band__row_236", + "ird_taxable_income_people_by_band__row_237", + "ird_taxable_income_people_by_band__row_238", + "ird_taxable_income_people_by_band__row_239", + "ird_taxable_income_people_by_band__row_240", + "ird_taxable_income_people_by_band__row_241", + "ird_taxable_income_people_by_band__row_242", + "ird_taxable_income_people_by_band__row_243", + "ird_taxable_income_people_by_band__row_244" + ], + "interval_table_ids": [ + "ird_taxable_income_national_ty2024" + ], + "required_measurement_binding": "ird_taxable_income_ty2027_v1" + } + ] }, "high": { - "available": false, - "transformations": [] + "transformations": [ + { + "operation": "scale_money_and_intervals", + "factor_id": "ird_ty2024_to_ty2027_high", + "reference_names": [ + "ird_taxable_income_total_by_band__row_8", + "ird_taxable_income_total_by_band__row_9", + "ird_taxable_income_total_by_band__row_10", + "ird_taxable_income_total_by_band__row_11", + "ird_taxable_income_total_by_band__row_12", + "ird_taxable_income_total_by_band__row_13", + "ird_taxable_income_total_by_band__row_14", + "ird_taxable_income_total_by_band__row_15", + "ird_taxable_income_total_by_band__row_16", + "ird_taxable_income_total_by_band__row_17", + "ird_taxable_income_total_by_band__row_18", + "ird_taxable_income_total_by_band__row_19", + "ird_taxable_income_total_by_band__row_20", + "ird_taxable_income_total_by_band__row_21", + "ird_taxable_income_total_by_band__row_22", + "ird_taxable_income_total_by_band__row_23", + "ird_taxable_income_total_by_band__row_24", + "ird_taxable_income_total_by_band__row_25", + "ird_taxable_income_total_by_band__row_26", + "ird_taxable_income_total_by_band__row_27", + "ird_taxable_income_total_by_band__row_28", + "ird_taxable_income_total_by_band__row_29", + "ird_taxable_income_total_by_band__row_30", + "ird_taxable_income_total_by_band__row_31", + "ird_taxable_income_total_by_band__row_32", + "ird_taxable_income_total_by_band__row_33", + "ird_taxable_income_total_by_band__row_34", + "ird_taxable_income_total_by_band__row_35", + "ird_taxable_income_total_by_band__row_36", + "ird_taxable_income_total_by_band__row_37", + "ird_taxable_income_total_by_band__row_38", + "ird_taxable_income_total_by_band__row_39", + "ird_taxable_income_total_by_band__row_40", + "ird_taxable_income_total_by_band__row_41", + "ird_taxable_income_total_by_band__row_42", + "ird_taxable_income_total_by_band__row_43", + "ird_taxable_income_total_by_band__row_44", + "ird_taxable_income_total_by_band__row_45", + "ird_taxable_income_total_by_band__row_46", + "ird_taxable_income_total_by_band__row_47", + "ird_taxable_income_total_by_band__row_48", + "ird_taxable_income_total_by_band__row_49", + "ird_taxable_income_total_by_band__row_50", + "ird_taxable_income_total_by_band__row_51", + "ird_taxable_income_total_by_band__row_52", + "ird_taxable_income_total_by_band__row_53", + "ird_taxable_income_total_by_band__row_54", + "ird_taxable_income_total_by_band__row_55", + "ird_taxable_income_total_by_band__row_56", + "ird_taxable_income_total_by_band__row_57", + "ird_taxable_income_total_by_band__row_58", + "ird_taxable_income_total_by_band__row_59", + "ird_taxable_income_total_by_band__row_60", + "ird_taxable_income_total_by_band__row_61", + "ird_taxable_income_total_by_band__row_62", + "ird_taxable_income_total_by_band__row_63", + "ird_taxable_income_total_by_band__row_64", + "ird_taxable_income_total_by_band__row_65", + "ird_taxable_income_total_by_band__row_66", + "ird_taxable_income_total_by_band__row_67", + "ird_taxable_income_total_by_band__row_68", + "ird_taxable_income_total_by_band__row_69", + "ird_taxable_income_total_by_band__row_70", + "ird_taxable_income_total_by_band__row_71", + "ird_taxable_income_total_by_band__row_72", + "ird_taxable_income_total_by_band__row_73", + "ird_taxable_income_total_by_band__row_74", + "ird_taxable_income_total_by_band__row_75", + "ird_taxable_income_total_by_band__row_76", + "ird_taxable_income_total_by_band__row_77", + "ird_taxable_income_total_by_band__row_78", + "ird_taxable_income_total_by_band__row_79", + "ird_taxable_income_total_by_band__row_80", + "ird_taxable_income_total_by_band__row_81", + "ird_taxable_income_total_by_band__row_82", + "ird_taxable_income_total_by_band__row_83", + "ird_taxable_income_total_by_band__row_84", + "ird_taxable_income_total_by_band__row_85", + "ird_taxable_income_total_by_band__row_86", + "ird_taxable_income_total_by_band__row_87", + "ird_taxable_income_total_by_band__row_88", + "ird_taxable_income_total_by_band__row_89", + "ird_taxable_income_total_by_band__row_90", + "ird_taxable_income_total_by_band__row_91", + "ird_taxable_income_total_by_band__row_92", + "ird_taxable_income_total_by_band__row_93", + "ird_taxable_income_total_by_band__row_94", + "ird_taxable_income_total_by_band__row_95", + "ird_taxable_income_total_by_band__row_96", + "ird_taxable_income_total_by_band__row_97", + "ird_taxable_income_total_by_band__row_98", + "ird_taxable_income_total_by_band__row_99", + "ird_taxable_income_total_by_band__row_100", + "ird_taxable_income_total_by_band__row_101", + "ird_taxable_income_total_by_band__row_102", + "ird_taxable_income_total_by_band__row_103", + "ird_taxable_income_total_by_band__row_104", + "ird_taxable_income_total_by_band__row_105", + "ird_taxable_income_total_by_band__row_106", + "ird_taxable_income_total_by_band__row_107", + "ird_taxable_income_total_by_band__row_108", + "ird_taxable_income_total_by_band__row_109", + "ird_taxable_income_total_by_band__row_110", + "ird_taxable_income_total_by_band__row_111", + "ird_taxable_income_total_by_band__row_112", + "ird_taxable_income_total_by_band__row_113", + "ird_taxable_income_total_by_band__row_114", + "ird_taxable_income_total_by_band__row_115", + "ird_taxable_income_total_by_band__row_116", + "ird_taxable_income_total_by_band__row_117", + "ird_taxable_income_total_by_band__row_118", + "ird_taxable_income_total_by_band__row_119", + "ird_taxable_income_total_by_band__row_120", + "ird_taxable_income_total_by_band__row_121", + "ird_taxable_income_total_by_band__row_122", + "ird_taxable_income_total_by_band__row_123", + "ird_taxable_income_total_by_band__row_124", + "ird_taxable_income_total_by_band__row_125", + "ird_taxable_income_total_by_band__row_126", + "ird_taxable_income_total_by_band__row_127", + "ird_taxable_income_total_by_band__row_128", + "ird_taxable_income_total_by_band__row_129", + "ird_taxable_income_total_by_band__row_130", + "ird_taxable_income_total_by_band__row_131", + "ird_taxable_income_total_by_band__row_132", + "ird_taxable_income_total_by_band__row_133", + "ird_taxable_income_total_by_band__row_134", + "ird_taxable_income_total_by_band__row_135", + "ird_taxable_income_total_by_band__row_136", + "ird_taxable_income_total_by_band__row_137", + "ird_taxable_income_total_by_band__row_138", + "ird_taxable_income_total_by_band__row_139", + "ird_taxable_income_total_by_band__row_140", + "ird_taxable_income_total_by_band__row_141", + "ird_taxable_income_total_by_band__row_142", + "ird_taxable_income_total_by_band__row_143", + "ird_taxable_income_total_by_band__row_144", + "ird_taxable_income_total_by_band__row_145", + "ird_taxable_income_total_by_band__row_146", + "ird_taxable_income_total_by_band__row_147", + "ird_taxable_income_total_by_band__row_148", + "ird_taxable_income_total_by_band__row_149", + "ird_taxable_income_total_by_band__row_150", + "ird_taxable_income_total_by_band__row_151", + "ird_taxable_income_total_by_band__row_152", + "ird_taxable_income_total_by_band__row_153", + "ird_taxable_income_total_by_band__row_154", + "ird_taxable_income_total_by_band__row_155", + "ird_taxable_income_total_by_band__row_156", + "ird_taxable_income_total_by_band__row_157", + "ird_taxable_income_total_by_band__row_158", + "ird_taxable_income_total_by_band__row_159", + "ird_taxable_income_total_by_band__row_160", + "ird_taxable_income_total_by_band__row_161", + "ird_taxable_income_total_by_band__row_162", + "ird_taxable_income_total_by_band__row_163", + "ird_taxable_income_total_by_band__row_164", + "ird_taxable_income_total_by_band__row_165", + "ird_taxable_income_total_by_band__row_166", + "ird_taxable_income_total_by_band__row_167", + "ird_taxable_income_total_by_band__row_168", + "ird_taxable_income_total_by_band__row_169", + "ird_taxable_income_total_by_band__row_170", + "ird_taxable_income_total_by_band__row_171", + "ird_taxable_income_total_by_band__row_172", + "ird_taxable_income_total_by_band__row_173", + "ird_taxable_income_total_by_band__row_174", + "ird_taxable_income_total_by_band__row_175", + "ird_taxable_income_total_by_band__row_176", + "ird_taxable_income_total_by_band__row_177", + "ird_taxable_income_total_by_band__row_178", + "ird_taxable_income_total_by_band__row_179", + "ird_taxable_income_total_by_band__row_180", + "ird_taxable_income_total_by_band__row_181", + "ird_taxable_income_total_by_band__row_182", + "ird_taxable_income_total_by_band__row_183", + "ird_taxable_income_total_by_band__row_184", + "ird_taxable_income_total_by_band__row_185", + "ird_taxable_income_total_by_band__row_186", + "ird_taxable_income_total_by_band__row_187", + "ird_taxable_income_total_by_band__row_188", + "ird_taxable_income_total_by_band__row_189", + "ird_taxable_income_total_by_band__row_190", + "ird_taxable_income_total_by_band__row_191", + "ird_taxable_income_total_by_band__row_192", + "ird_taxable_income_total_by_band__row_193", + "ird_taxable_income_total_by_band__row_194", + "ird_taxable_income_total_by_band__row_195", + "ird_taxable_income_total_by_band__row_196", + "ird_taxable_income_total_by_band__row_197", + "ird_taxable_income_total_by_band__row_198", + "ird_taxable_income_total_by_band__row_199", + "ird_taxable_income_total_by_band__row_200", + "ird_taxable_income_total_by_band__row_201", + "ird_taxable_income_total_by_band__row_202", + "ird_taxable_income_total_by_band__row_203", + "ird_taxable_income_total_by_band__row_204", + "ird_taxable_income_total_by_band__row_205", + "ird_taxable_income_total_by_band__row_206", + "ird_taxable_income_total_by_band__row_207", + "ird_taxable_income_total_by_band__row_208", + "ird_taxable_income_total_by_band__row_209", + "ird_taxable_income_total_by_band__row_210", + "ird_taxable_income_total_by_band__row_211", + "ird_taxable_income_total_by_band__row_212", + "ird_taxable_income_total_by_band__row_213", + "ird_taxable_income_total_by_band__row_214", + "ird_taxable_income_total_by_band__row_215", + "ird_taxable_income_total_by_band__row_216", + "ird_taxable_income_total_by_band__row_217", + "ird_taxable_income_total_by_band__row_218", + "ird_taxable_income_total_by_band__row_219", + "ird_taxable_income_total_by_band__row_220", + "ird_taxable_income_total_by_band__row_221", + "ird_taxable_income_total_by_band__row_222", + "ird_taxable_income_total_by_band__row_223", + "ird_taxable_income_total_by_band__row_224", + "ird_taxable_income_total_by_band__row_225", + "ird_taxable_income_total_by_band__row_226", + "ird_taxable_income_total_by_band__row_227", + "ird_taxable_income_total_by_band__row_228", + "ird_taxable_income_total_by_band__row_229", + "ird_taxable_income_total_by_band__row_230", + "ird_taxable_income_total_by_band__row_231", + "ird_taxable_income_total_by_band__row_232", + "ird_taxable_income_total_by_band__row_233", + "ird_taxable_income_total_by_band__row_234", + "ird_taxable_income_total_by_band__row_235", + "ird_taxable_income_total_by_band__row_236", + "ird_taxable_income_total_by_band__row_237", + "ird_taxable_income_total_by_band__row_238", + "ird_taxable_income_total_by_band__row_239", + "ird_taxable_income_total_by_band__row_240", + "ird_taxable_income_total_by_band__row_241", + "ird_taxable_income_total_by_band__row_242", + "ird_taxable_income_total_by_band__row_243", + "ird_taxable_income_total_by_band__row_244" + ], + "count_reference_names": [ + "ird_taxable_income_people_by_band__row_8", + "ird_taxable_income_people_by_band__row_9", + "ird_taxable_income_people_by_band__row_10", + "ird_taxable_income_people_by_band__row_11", + "ird_taxable_income_people_by_band__row_12", + "ird_taxable_income_people_by_band__row_13", + "ird_taxable_income_people_by_band__row_14", + "ird_taxable_income_people_by_band__row_15", + "ird_taxable_income_people_by_band__row_16", + "ird_taxable_income_people_by_band__row_17", + "ird_taxable_income_people_by_band__row_18", + "ird_taxable_income_people_by_band__row_19", + "ird_taxable_income_people_by_band__row_20", + "ird_taxable_income_people_by_band__row_21", + "ird_taxable_income_people_by_band__row_22", + "ird_taxable_income_people_by_band__row_23", + "ird_taxable_income_people_by_band__row_24", + "ird_taxable_income_people_by_band__row_25", + "ird_taxable_income_people_by_band__row_26", + "ird_taxable_income_people_by_band__row_27", + "ird_taxable_income_people_by_band__row_28", + "ird_taxable_income_people_by_band__row_29", + "ird_taxable_income_people_by_band__row_30", + "ird_taxable_income_people_by_band__row_31", + "ird_taxable_income_people_by_band__row_32", + "ird_taxable_income_people_by_band__row_33", + "ird_taxable_income_people_by_band__row_34", + "ird_taxable_income_people_by_band__row_35", + "ird_taxable_income_people_by_band__row_36", + "ird_taxable_income_people_by_band__row_37", + "ird_taxable_income_people_by_band__row_38", + "ird_taxable_income_people_by_band__row_39", + "ird_taxable_income_people_by_band__row_40", + "ird_taxable_income_people_by_band__row_41", + "ird_taxable_income_people_by_band__row_42", + "ird_taxable_income_people_by_band__row_43", + "ird_taxable_income_people_by_band__row_44", + "ird_taxable_income_people_by_band__row_45", + "ird_taxable_income_people_by_band__row_46", + "ird_taxable_income_people_by_band__row_47", + "ird_taxable_income_people_by_band__row_48", + "ird_taxable_income_people_by_band__row_49", + "ird_taxable_income_people_by_band__row_50", + "ird_taxable_income_people_by_band__row_51", + "ird_taxable_income_people_by_band__row_52", + "ird_taxable_income_people_by_band__row_53", + "ird_taxable_income_people_by_band__row_54", + "ird_taxable_income_people_by_band__row_55", + "ird_taxable_income_people_by_band__row_56", + "ird_taxable_income_people_by_band__row_57", + "ird_taxable_income_people_by_band__row_58", + "ird_taxable_income_people_by_band__row_59", + "ird_taxable_income_people_by_band__row_60", + "ird_taxable_income_people_by_band__row_61", + "ird_taxable_income_people_by_band__row_62", + "ird_taxable_income_people_by_band__row_63", + "ird_taxable_income_people_by_band__row_64", + "ird_taxable_income_people_by_band__row_65", + "ird_taxable_income_people_by_band__row_66", + "ird_taxable_income_people_by_band__row_67", + "ird_taxable_income_people_by_band__row_68", + "ird_taxable_income_people_by_band__row_69", + "ird_taxable_income_people_by_band__row_70", + "ird_taxable_income_people_by_band__row_71", + "ird_taxable_income_people_by_band__row_72", + "ird_taxable_income_people_by_band__row_73", + "ird_taxable_income_people_by_band__row_74", + "ird_taxable_income_people_by_band__row_75", + "ird_taxable_income_people_by_band__row_76", + "ird_taxable_income_people_by_band__row_77", + "ird_taxable_income_people_by_band__row_78", + "ird_taxable_income_people_by_band__row_79", + "ird_taxable_income_people_by_band__row_80", + "ird_taxable_income_people_by_band__row_81", + "ird_taxable_income_people_by_band__row_82", + "ird_taxable_income_people_by_band__row_83", + "ird_taxable_income_people_by_band__row_84", + "ird_taxable_income_people_by_band__row_85", + "ird_taxable_income_people_by_band__row_86", + "ird_taxable_income_people_by_band__row_87", + "ird_taxable_income_people_by_band__row_88", + "ird_taxable_income_people_by_band__row_89", + "ird_taxable_income_people_by_band__row_90", + "ird_taxable_income_people_by_band__row_91", + "ird_taxable_income_people_by_band__row_92", + "ird_taxable_income_people_by_band__row_93", + "ird_taxable_income_people_by_band__row_94", + "ird_taxable_income_people_by_band__row_95", + "ird_taxable_income_people_by_band__row_96", + "ird_taxable_income_people_by_band__row_97", + "ird_taxable_income_people_by_band__row_98", + "ird_taxable_income_people_by_band__row_99", + "ird_taxable_income_people_by_band__row_100", + "ird_taxable_income_people_by_band__row_101", + "ird_taxable_income_people_by_band__row_102", + "ird_taxable_income_people_by_band__row_103", + "ird_taxable_income_people_by_band__row_104", + "ird_taxable_income_people_by_band__row_105", + "ird_taxable_income_people_by_band__row_106", + "ird_taxable_income_people_by_band__row_107", + "ird_taxable_income_people_by_band__row_108", + "ird_taxable_income_people_by_band__row_109", + "ird_taxable_income_people_by_band__row_110", + "ird_taxable_income_people_by_band__row_111", + "ird_taxable_income_people_by_band__row_112", + "ird_taxable_income_people_by_band__row_113", + "ird_taxable_income_people_by_band__row_114", + "ird_taxable_income_people_by_band__row_115", + "ird_taxable_income_people_by_band__row_116", + "ird_taxable_income_people_by_band__row_117", + "ird_taxable_income_people_by_band__row_118", + "ird_taxable_income_people_by_band__row_119", + "ird_taxable_income_people_by_band__row_120", + "ird_taxable_income_people_by_band__row_121", + "ird_taxable_income_people_by_band__row_122", + "ird_taxable_income_people_by_band__row_123", + "ird_taxable_income_people_by_band__row_124", + "ird_taxable_income_people_by_band__row_125", + "ird_taxable_income_people_by_band__row_126", + "ird_taxable_income_people_by_band__row_127", + "ird_taxable_income_people_by_band__row_128", + "ird_taxable_income_people_by_band__row_129", + "ird_taxable_income_people_by_band__row_130", + "ird_taxable_income_people_by_band__row_131", + "ird_taxable_income_people_by_band__row_132", + "ird_taxable_income_people_by_band__row_133", + "ird_taxable_income_people_by_band__row_134", + "ird_taxable_income_people_by_band__row_135", + "ird_taxable_income_people_by_band__row_136", + "ird_taxable_income_people_by_band__row_137", + "ird_taxable_income_people_by_band__row_138", + "ird_taxable_income_people_by_band__row_139", + "ird_taxable_income_people_by_band__row_140", + "ird_taxable_income_people_by_band__row_141", + "ird_taxable_income_people_by_band__row_142", + "ird_taxable_income_people_by_band__row_143", + "ird_taxable_income_people_by_band__row_144", + "ird_taxable_income_people_by_band__row_145", + "ird_taxable_income_people_by_band__row_146", + "ird_taxable_income_people_by_band__row_147", + "ird_taxable_income_people_by_band__row_148", + "ird_taxable_income_people_by_band__row_149", + "ird_taxable_income_people_by_band__row_150", + "ird_taxable_income_people_by_band__row_151", + "ird_taxable_income_people_by_band__row_152", + "ird_taxable_income_people_by_band__row_153", + "ird_taxable_income_people_by_band__row_154", + "ird_taxable_income_people_by_band__row_155", + "ird_taxable_income_people_by_band__row_156", + "ird_taxable_income_people_by_band__row_157", + "ird_taxable_income_people_by_band__row_158", + "ird_taxable_income_people_by_band__row_159", + "ird_taxable_income_people_by_band__row_160", + "ird_taxable_income_people_by_band__row_161", + "ird_taxable_income_people_by_band__row_162", + "ird_taxable_income_people_by_band__row_163", + "ird_taxable_income_people_by_band__row_164", + "ird_taxable_income_people_by_band__row_165", + "ird_taxable_income_people_by_band__row_166", + "ird_taxable_income_people_by_band__row_167", + "ird_taxable_income_people_by_band__row_168", + "ird_taxable_income_people_by_band__row_169", + "ird_taxable_income_people_by_band__row_170", + "ird_taxable_income_people_by_band__row_171", + "ird_taxable_income_people_by_band__row_172", + "ird_taxable_income_people_by_band__row_173", + "ird_taxable_income_people_by_band__row_174", + "ird_taxable_income_people_by_band__row_175", + "ird_taxable_income_people_by_band__row_176", + "ird_taxable_income_people_by_band__row_177", + "ird_taxable_income_people_by_band__row_178", + "ird_taxable_income_people_by_band__row_179", + "ird_taxable_income_people_by_band__row_180", + "ird_taxable_income_people_by_band__row_181", + "ird_taxable_income_people_by_band__row_182", + "ird_taxable_income_people_by_band__row_183", + "ird_taxable_income_people_by_band__row_184", + "ird_taxable_income_people_by_band__row_185", + "ird_taxable_income_people_by_band__row_186", + "ird_taxable_income_people_by_band__row_187", + "ird_taxable_income_people_by_band__row_188", + "ird_taxable_income_people_by_band__row_189", + "ird_taxable_income_people_by_band__row_190", + "ird_taxable_income_people_by_band__row_191", + "ird_taxable_income_people_by_band__row_192", + "ird_taxable_income_people_by_band__row_193", + "ird_taxable_income_people_by_band__row_194", + "ird_taxable_income_people_by_band__row_195", + "ird_taxable_income_people_by_band__row_196", + "ird_taxable_income_people_by_band__row_197", + "ird_taxable_income_people_by_band__row_198", + "ird_taxable_income_people_by_band__row_199", + "ird_taxable_income_people_by_band__row_200", + "ird_taxable_income_people_by_band__row_201", + "ird_taxable_income_people_by_band__row_202", + "ird_taxable_income_people_by_band__row_203", + "ird_taxable_income_people_by_band__row_204", + "ird_taxable_income_people_by_band__row_205", + "ird_taxable_income_people_by_band__row_206", + "ird_taxable_income_people_by_band__row_207", + "ird_taxable_income_people_by_band__row_208", + "ird_taxable_income_people_by_band__row_209", + "ird_taxable_income_people_by_band__row_210", + "ird_taxable_income_people_by_band__row_211", + "ird_taxable_income_people_by_band__row_212", + "ird_taxable_income_people_by_band__row_213", + "ird_taxable_income_people_by_band__row_214", + "ird_taxable_income_people_by_band__row_215", + "ird_taxable_income_people_by_band__row_216", + "ird_taxable_income_people_by_band__row_217", + "ird_taxable_income_people_by_band__row_218", + "ird_taxable_income_people_by_band__row_219", + "ird_taxable_income_people_by_band__row_220", + "ird_taxable_income_people_by_band__row_221", + "ird_taxable_income_people_by_band__row_222", + "ird_taxable_income_people_by_band__row_223", + "ird_taxable_income_people_by_band__row_224", + "ird_taxable_income_people_by_band__row_225", + "ird_taxable_income_people_by_band__row_226", + "ird_taxable_income_people_by_band__row_227", + "ird_taxable_income_people_by_band__row_228", + "ird_taxable_income_people_by_band__row_229", + "ird_taxable_income_people_by_band__row_230", + "ird_taxable_income_people_by_band__row_231", + "ird_taxable_income_people_by_band__row_232", + "ird_taxable_income_people_by_band__row_233", + "ird_taxable_income_people_by_band__row_234", + "ird_taxable_income_people_by_band__row_235", + "ird_taxable_income_people_by_band__row_236", + "ird_taxable_income_people_by_band__row_237", + "ird_taxable_income_people_by_band__row_238", + "ird_taxable_income_people_by_band__row_239", + "ird_taxable_income_people_by_band__row_240", + "ird_taxable_income_people_by_band__row_241", + "ird_taxable_income_people_by_band__row_242", + "ird_taxable_income_people_by_band__row_243", + "ird_taxable_income_people_by_band__row_244" + ], + "interval_table_ids": [ + "ird_taxable_income_national_ty2024" + ], + "required_measurement_binding": "ird_taxable_income_ty2027_v1" + } + ] } } } diff --git a/packages/microcosm-build/src/microcosm/build/nz/target_references.json b/packages/microcosm-build/src/microcosm/build/nz/target_references.json index bbe44aee98..8137a17bc3 100644 --- a/packages/microcosm-build/src/microcosm/build/nz/target_references.json +++ b/packages/microcosm-build/src/microcosm/build/nz/target_references.json @@ -5,7 +5,8 @@ "allowed_value_operations": [ "identity", "rolled_forward_by_ratio", - "allocated_residual_by_ratio" + "allocated_residual_by_ratio", + "linear_combination" ], "target_references": [ { @@ -25597,14 +25598,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -25619,7 +25624,7 @@ "target_label": "TY2026-27 ird taxable income people by band nil (parked)" }, "filter": "taxable_income_band_row_8_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_9", @@ -25649,14 +25654,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -25671,7 +25680,7 @@ "target_label": "TY2026-27 ird taxable income people by band $0.01 - $100 (parked)" }, "filter": "taxable_income_band_row_9_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_10", @@ -25701,14 +25710,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -25723,7 +25736,7 @@ "target_label": "TY2026-27 ird taxable income people by band $101 - $1,000 (parked)" }, "filter": "taxable_income_band_row_10_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_11", @@ -25753,14 +25766,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -25775,7 +25792,7 @@ "target_label": "TY2026-27 ird taxable income people by band $1,001 - $2,000 (parked)" }, "filter": "taxable_income_band_row_11_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_12", @@ -25805,14 +25822,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -25827,7 +25848,7 @@ "target_label": "TY2026-27 ird taxable income people by band $2,001 - $3,000 (parked)" }, "filter": "taxable_income_band_row_12_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_13", @@ -25857,14 +25878,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -25879,7 +25904,7 @@ "target_label": "TY2026-27 ird taxable income people by band $3,001 - $4,000 (parked)" }, "filter": "taxable_income_band_row_13_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_14", @@ -25909,14 +25934,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -25931,7 +25960,7 @@ "target_label": "TY2026-27 ird taxable income people by band $4,001 - $5,000 (parked)" }, "filter": "taxable_income_band_row_14_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_15", @@ -25961,14 +25990,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -25983,7 +26016,7 @@ "target_label": "TY2026-27 ird taxable income people by band $5,001 - $6,000 (parked)" }, "filter": "taxable_income_band_row_15_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_16", @@ -26013,14 +26046,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26035,7 +26072,7 @@ "target_label": "TY2026-27 ird taxable income people by band $6,001 - $7,000 (parked)" }, "filter": "taxable_income_band_row_16_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_17", @@ -26065,14 +26102,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26087,7 +26128,7 @@ "target_label": "TY2026-27 ird taxable income people by band $7,001 - $8,000 (parked)" }, "filter": "taxable_income_band_row_17_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_18", @@ -26117,14 +26158,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26139,7 +26184,7 @@ "target_label": "TY2026-27 ird taxable income people by band $8,001 - $9,000 (parked)" }, "filter": "taxable_income_band_row_18_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_19", @@ -26169,14 +26214,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26191,7 +26240,7 @@ "target_label": "TY2026-27 ird taxable income people by band $9,001 - $10,000 (parked)" }, "filter": "taxable_income_band_row_19_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_20", @@ -26221,14 +26270,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26243,7 +26296,7 @@ "target_label": "TY2026-27 ird taxable income people by band $10,001 - $11,000 (parked)" }, "filter": "taxable_income_band_row_20_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_21", @@ -26273,14 +26326,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26295,7 +26352,7 @@ "target_label": "TY2026-27 ird taxable income people by band $11,001 - $12,000 (parked)" }, "filter": "taxable_income_band_row_21_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_22", @@ -26325,14 +26382,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26347,7 +26408,7 @@ "target_label": "TY2026-27 ird taxable income people by band $12,001 - $13,000 (parked)" }, "filter": "taxable_income_band_row_22_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_23", @@ -26377,14 +26438,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26399,7 +26464,7 @@ "target_label": "TY2026-27 ird taxable income people by band $13,001 - $14,000 (parked)" }, "filter": "taxable_income_band_row_23_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_24", @@ -26429,14 +26494,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26451,7 +26520,7 @@ "target_label": "TY2026-27 ird taxable income people by band $14,001 - $15,000 (parked)" }, "filter": "taxable_income_band_row_24_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_25", @@ -26481,14 +26550,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26503,7 +26576,7 @@ "target_label": "TY2026-27 ird taxable income people by band $15,001 - $16,000 (parked)" }, "filter": "taxable_income_band_row_25_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_26", @@ -26533,14 +26606,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26555,7 +26632,7 @@ "target_label": "TY2026-27 ird taxable income people by band $16,001 - $17,000 (parked)" }, "filter": "taxable_income_band_row_26_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_27", @@ -26585,14 +26662,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26607,7 +26688,7 @@ "target_label": "TY2026-27 ird taxable income people by band $17,001 - $18,000 (parked)" }, "filter": "taxable_income_band_row_27_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_28", @@ -26637,14 +26718,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26659,7 +26744,7 @@ "target_label": "TY2026-27 ird taxable income people by band $18,001 - $19,000 (parked)" }, "filter": "taxable_income_band_row_28_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_29", @@ -26689,14 +26774,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26711,7 +26800,7 @@ "target_label": "TY2026-27 ird taxable income people by band $19,001 - $20,000 (parked)" }, "filter": "taxable_income_band_row_29_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_30", @@ -26741,14 +26830,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26763,7 +26856,7 @@ "target_label": "TY2026-27 ird taxable income people by band $20,000 - $21,000 (parked)" }, "filter": "taxable_income_band_row_30_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_31", @@ -26793,14 +26886,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26815,7 +26912,7 @@ "target_label": "TY2026-27 ird taxable income people by band $21,001 - $22,000 (parked)" }, "filter": "taxable_income_band_row_31_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_32", @@ -26845,14 +26942,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26867,7 +26968,7 @@ "target_label": "TY2026-27 ird taxable income people by band $22,001 - $23,000 (parked)" }, "filter": "taxable_income_band_row_32_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_33", @@ -26897,14 +26998,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26919,7 +27024,7 @@ "target_label": "TY2026-27 ird taxable income people by band $23,001 - $24,000 (parked)" }, "filter": "taxable_income_band_row_33_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_34", @@ -26949,14 +27054,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -26971,7 +27080,7 @@ "target_label": "TY2026-27 ird taxable income people by band $24,001 - $25,000 (parked)" }, "filter": "taxable_income_band_row_34_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_35", @@ -27001,14 +27110,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27023,7 +27136,7 @@ "target_label": "TY2026-27 ird taxable income people by band $25,001 - $26,000 (parked)" }, "filter": "taxable_income_band_row_35_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_36", @@ -27053,14 +27166,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27075,7 +27192,7 @@ "target_label": "TY2026-27 ird taxable income people by band $26,001 - $27,000 (parked)" }, "filter": "taxable_income_band_row_36_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_37", @@ -27105,14 +27222,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27127,7 +27248,7 @@ "target_label": "TY2026-27 ird taxable income people by band $27,001 - $28,000 (parked)" }, "filter": "taxable_income_band_row_37_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_38", @@ -27157,14 +27278,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27179,7 +27304,7 @@ "target_label": "TY2026-27 ird taxable income people by band $28,001 - $29,000 (parked)" }, "filter": "taxable_income_band_row_38_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_39", @@ -27209,14 +27334,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27231,7 +27360,7 @@ "target_label": "TY2026-27 ird taxable income people by band $29,001 - $30,000 (parked)" }, "filter": "taxable_income_band_row_39_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_40", @@ -27261,14 +27390,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27283,7 +27416,7 @@ "target_label": "TY2026-27 ird taxable income people by band $30,001 - $31,000 (parked)" }, "filter": "taxable_income_band_row_40_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_41", @@ -27313,14 +27446,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27335,7 +27472,7 @@ "target_label": "TY2026-27 ird taxable income people by band $31,001 - $32,000 (parked)" }, "filter": "taxable_income_band_row_41_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_42", @@ -27365,14 +27502,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27387,7 +27528,7 @@ "target_label": "TY2026-27 ird taxable income people by band $32,001 - $33,000 (parked)" }, "filter": "taxable_income_band_row_42_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_43", @@ -27417,14 +27558,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27439,7 +27584,7 @@ "target_label": "TY2026-27 ird taxable income people by band $33,001 - $34,000 (parked)" }, "filter": "taxable_income_band_row_43_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_44", @@ -27469,14 +27614,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27491,7 +27640,7 @@ "target_label": "TY2026-27 ird taxable income people by band $34,001 - $35,000 (parked)" }, "filter": "taxable_income_band_row_44_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_45", @@ -27521,14 +27670,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27543,7 +27696,7 @@ "target_label": "TY2026-27 ird taxable income people by band $35,001 - $36,000 (parked)" }, "filter": "taxable_income_band_row_45_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_46", @@ -27573,14 +27726,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27595,7 +27752,7 @@ "target_label": "TY2026-27 ird taxable income people by band $36,001 - $37,000 (parked)" }, "filter": "taxable_income_band_row_46_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_47", @@ -27625,14 +27782,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27647,7 +27808,7 @@ "target_label": "TY2026-27 ird taxable income people by band $37,001 - $38,000 (parked)" }, "filter": "taxable_income_band_row_47_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_48", @@ -27677,14 +27838,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27699,7 +27864,7 @@ "target_label": "TY2026-27 ird taxable income people by band $38,001 - $39,000 (parked)" }, "filter": "taxable_income_band_row_48_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_49", @@ -27729,14 +27894,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27751,7 +27920,7 @@ "target_label": "TY2026-27 ird taxable income people by band $39,001 - $40,000 (parked)" }, "filter": "taxable_income_band_row_49_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_50", @@ -27781,14 +27950,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27803,7 +27976,7 @@ "target_label": "TY2026-27 ird taxable income people by band $40,001 - $41,000 (parked)" }, "filter": "taxable_income_band_row_50_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_51", @@ -27833,14 +28006,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27855,7 +28032,7 @@ "target_label": "TY2026-27 ird taxable income people by band $41,001 - $42,000 (parked)" }, "filter": "taxable_income_band_row_51_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_52", @@ -27885,14 +28062,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27907,7 +28088,7 @@ "target_label": "TY2026-27 ird taxable income people by band $42,001 - $43,000 (parked)" }, "filter": "taxable_income_band_row_52_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_53", @@ -27937,14 +28118,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -27959,7 +28144,7 @@ "target_label": "TY2026-27 ird taxable income people by band $43,001 - $44,000 (parked)" }, "filter": "taxable_income_band_row_53_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_54", @@ -27989,14 +28174,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28011,7 +28200,7 @@ "target_label": "TY2026-27 ird taxable income people by band $44,001 - $45,000 (parked)" }, "filter": "taxable_income_band_row_54_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_55", @@ -28041,14 +28230,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28063,7 +28256,7 @@ "target_label": "TY2026-27 ird taxable income people by band $45,001 - $46,000 (parked)" }, "filter": "taxable_income_band_row_55_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_56", @@ -28093,14 +28286,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28115,7 +28312,7 @@ "target_label": "TY2026-27 ird taxable income people by band $46,001 - $47,000 (parked)" }, "filter": "taxable_income_band_row_56_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_57", @@ -28145,14 +28342,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28167,7 +28368,7 @@ "target_label": "TY2026-27 ird taxable income people by band $47,001 - $48,000 (parked)" }, "filter": "taxable_income_band_row_57_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_58", @@ -28197,14 +28398,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28219,7 +28424,7 @@ "target_label": "TY2026-27 ird taxable income people by band $48,001 - $49,000 (parked)" }, "filter": "taxable_income_band_row_58_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_59", @@ -28249,14 +28454,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28271,7 +28480,7 @@ "target_label": "TY2026-27 ird taxable income people by band $49,001 - $50,000 (parked)" }, "filter": "taxable_income_band_row_59_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_60", @@ -28301,14 +28510,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28323,7 +28536,7 @@ "target_label": "TY2026-27 ird taxable income people by band $50,000 - $51,000 (parked)" }, "filter": "taxable_income_band_row_60_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_61", @@ -28353,14 +28566,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28375,7 +28592,7 @@ "target_label": "TY2026-27 ird taxable income people by band $51,001 - $52,000 (parked)" }, "filter": "taxable_income_band_row_61_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_62", @@ -28405,14 +28622,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28427,7 +28648,7 @@ "target_label": "TY2026-27 ird taxable income people by band $52,001 - $53,000 (parked)" }, "filter": "taxable_income_band_row_62_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_63", @@ -28457,14 +28678,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28479,7 +28704,7 @@ "target_label": "TY2026-27 ird taxable income people by band $53,001 - $54,000 (parked)" }, "filter": "taxable_income_band_row_63_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_64", @@ -28509,14 +28734,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28531,7 +28760,7 @@ "target_label": "TY2026-27 ird taxable income people by band $54,001 - $55,000 (parked)" }, "filter": "taxable_income_band_row_64_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_65", @@ -28561,14 +28790,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28583,7 +28816,7 @@ "target_label": "TY2026-27 ird taxable income people by band $55,001 - $56,000 (parked)" }, "filter": "taxable_income_band_row_65_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_66", @@ -28613,14 +28846,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28635,7 +28872,7 @@ "target_label": "TY2026-27 ird taxable income people by band $56,001 - $57,000 (parked)" }, "filter": "taxable_income_band_row_66_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_67", @@ -28665,14 +28902,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28687,7 +28928,7 @@ "target_label": "TY2026-27 ird taxable income people by band $57,001 - $58,000 (parked)" }, "filter": "taxable_income_band_row_67_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_68", @@ -28717,14 +28958,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28739,7 +28984,7 @@ "target_label": "TY2026-27 ird taxable income people by band $58,001 - $59,000 (parked)" }, "filter": "taxable_income_band_row_68_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_69", @@ -28769,14 +29014,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28791,7 +29040,7 @@ "target_label": "TY2026-27 ird taxable income people by band $59,001 - $60,000 (parked)" }, "filter": "taxable_income_band_row_69_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_70", @@ -28821,14 +29070,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28843,7 +29096,7 @@ "target_label": "TY2026-27 ird taxable income people by band $60,001 - $61,000 (parked)" }, "filter": "taxable_income_band_row_70_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_71", @@ -28873,14 +29126,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28895,7 +29152,7 @@ "target_label": "TY2026-27 ird taxable income people by band $61,001 - $62,000 (parked)" }, "filter": "taxable_income_band_row_71_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_72", @@ -28925,14 +29182,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28947,7 +29208,7 @@ "target_label": "TY2026-27 ird taxable income people by band $62,001 - $63,000 (parked)" }, "filter": "taxable_income_band_row_72_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_73", @@ -28977,14 +29238,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -28999,7 +29264,7 @@ "target_label": "TY2026-27 ird taxable income people by band $63,001 - $64,000 (parked)" }, "filter": "taxable_income_band_row_73_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_74", @@ -29029,14 +29294,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29051,7 +29320,7 @@ "target_label": "TY2026-27 ird taxable income people by band $64,001 - $65,000 (parked)" }, "filter": "taxable_income_band_row_74_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_75", @@ -29081,14 +29350,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29103,7 +29376,7 @@ "target_label": "TY2026-27 ird taxable income people by band $65,001 - $66,000 (parked)" }, "filter": "taxable_income_band_row_75_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_76", @@ -29133,14 +29406,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29155,7 +29432,7 @@ "target_label": "TY2026-27 ird taxable income people by band $66,001 - $67,000 (parked)" }, "filter": "taxable_income_band_row_76_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_77", @@ -29185,14 +29462,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29207,7 +29488,7 @@ "target_label": "TY2026-27 ird taxable income people by band $67,001 - $68,000 (parked)" }, "filter": "taxable_income_band_row_77_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_78", @@ -29237,14 +29518,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29259,7 +29544,7 @@ "target_label": "TY2026-27 ird taxable income people by band $68,001 - $69,000 (parked)" }, "filter": "taxable_income_band_row_78_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_79", @@ -29289,14 +29574,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29311,7 +29600,7 @@ "target_label": "TY2026-27 ird taxable income people by band $69,001 - $70,000 (parked)" }, "filter": "taxable_income_band_row_79_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_80", @@ -29341,14 +29630,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29363,7 +29656,7 @@ "target_label": "TY2026-27 ird taxable income people by band $70,001 - $71,000 (parked)" }, "filter": "taxable_income_band_row_80_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_81", @@ -29393,14 +29686,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29415,7 +29712,7 @@ "target_label": "TY2026-27 ird taxable income people by band $71,001 - $72,000 (parked)" }, "filter": "taxable_income_band_row_81_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_82", @@ -29445,14 +29742,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29467,7 +29768,7 @@ "target_label": "TY2026-27 ird taxable income people by band $72,001 - $73,000 (parked)" }, "filter": "taxable_income_band_row_82_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_83", @@ -29497,14 +29798,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29519,7 +29824,7 @@ "target_label": "TY2026-27 ird taxable income people by band $73,001 - $74,000 (parked)" }, "filter": "taxable_income_band_row_83_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_84", @@ -29549,14 +29854,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29571,7 +29880,7 @@ "target_label": "TY2026-27 ird taxable income people by band $74,001 - $75,000 (parked)" }, "filter": "taxable_income_band_row_84_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_85", @@ -29601,14 +29910,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29623,7 +29936,7 @@ "target_label": "TY2026-27 ird taxable income people by band $75,001 - $76,000 (parked)" }, "filter": "taxable_income_band_row_85_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_86", @@ -29653,14 +29966,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29675,7 +29992,7 @@ "target_label": "TY2026-27 ird taxable income people by band $76,001 - $77,000 (parked)" }, "filter": "taxable_income_band_row_86_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_87", @@ -29705,14 +30022,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29727,7 +30048,7 @@ "target_label": "TY2026-27 ird taxable income people by band $77,001 - $78,000 (parked)" }, "filter": "taxable_income_band_row_87_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_88", @@ -29757,14 +30078,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29779,7 +30104,7 @@ "target_label": "TY2026-27 ird taxable income people by band $78,001 - $79,000 (parked)" }, "filter": "taxable_income_band_row_88_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_89", @@ -29809,14 +30134,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29831,7 +30160,7 @@ "target_label": "TY2026-27 ird taxable income people by band $79,001 - $80,000 (parked)" }, "filter": "taxable_income_band_row_89_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_90", @@ -29861,14 +30190,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29883,7 +30216,7 @@ "target_label": "TY2026-27 ird taxable income people by band $80,000 - $81,000 (parked)" }, "filter": "taxable_income_band_row_90_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_91", @@ -29913,14 +30246,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29935,7 +30272,7 @@ "target_label": "TY2026-27 ird taxable income people by band $81,001 - $82,000 (parked)" }, "filter": "taxable_income_band_row_91_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_92", @@ -29965,14 +30302,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -29987,7 +30328,7 @@ "target_label": "TY2026-27 ird taxable income people by band $82,001 - $83,000 (parked)" }, "filter": "taxable_income_band_row_92_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_93", @@ -30017,14 +30358,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30039,7 +30384,7 @@ "target_label": "TY2026-27 ird taxable income people by band $83,001 - $84,000 (parked)" }, "filter": "taxable_income_band_row_93_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_94", @@ -30069,14 +30414,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30091,7 +30440,7 @@ "target_label": "TY2026-27 ird taxable income people by band $84,001 - $85,000 (parked)" }, "filter": "taxable_income_band_row_94_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_95", @@ -30121,14 +30470,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30143,7 +30496,7 @@ "target_label": "TY2026-27 ird taxable income people by band $85,001 - $86,000 (parked)" }, "filter": "taxable_income_band_row_95_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_96", @@ -30173,14 +30526,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30195,7 +30552,7 @@ "target_label": "TY2026-27 ird taxable income people by band $86,001 - $87,000 (parked)" }, "filter": "taxable_income_band_row_96_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_97", @@ -30225,14 +30582,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30247,7 +30608,7 @@ "target_label": "TY2026-27 ird taxable income people by band $87,001 - $88,000 (parked)" }, "filter": "taxable_income_band_row_97_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_98", @@ -30277,14 +30638,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30299,7 +30664,7 @@ "target_label": "TY2026-27 ird taxable income people by band $88,001 - $89,000 (parked)" }, "filter": "taxable_income_band_row_98_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_99", @@ -30329,14 +30694,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30351,7 +30720,7 @@ "target_label": "TY2026-27 ird taxable income people by band $89,001 - $90,000 (parked)" }, "filter": "taxable_income_band_row_99_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_100", @@ -30381,14 +30750,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30403,7 +30776,7 @@ "target_label": "TY2026-27 ird taxable income people by band $90,001 - $91,000 (parked)" }, "filter": "taxable_income_band_row_100_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_101", @@ -30433,14 +30806,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30455,7 +30832,7 @@ "target_label": "TY2026-27 ird taxable income people by band $91,001 - $92,000 (parked)" }, "filter": "taxable_income_band_row_101_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_102", @@ -30485,14 +30862,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30507,7 +30888,7 @@ "target_label": "TY2026-27 ird taxable income people by band $92,001 - $93,000 (parked)" }, "filter": "taxable_income_band_row_102_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_103", @@ -30537,14 +30918,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30559,7 +30944,7 @@ "target_label": "TY2026-27 ird taxable income people by band $93,001 - $94,000 (parked)" }, "filter": "taxable_income_band_row_103_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_104", @@ -30589,14 +30974,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30611,7 +31000,7 @@ "target_label": "TY2026-27 ird taxable income people by band $94,001 - $95,000 (parked)" }, "filter": "taxable_income_band_row_104_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_105", @@ -30641,14 +31030,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30663,7 +31056,7 @@ "target_label": "TY2026-27 ird taxable income people by band $95,001 - $96,000 (parked)" }, "filter": "taxable_income_band_row_105_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_106", @@ -30693,14 +31086,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30715,7 +31112,7 @@ "target_label": "TY2026-27 ird taxable income people by band $96,001 - $97,000 (parked)" }, "filter": "taxable_income_band_row_106_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_107", @@ -30745,14 +31142,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30767,7 +31168,7 @@ "target_label": "TY2026-27 ird taxable income people by band $97,001 - $98,000 (parked)" }, "filter": "taxable_income_band_row_107_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_108", @@ -30797,14 +31198,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30819,7 +31224,7 @@ "target_label": "TY2026-27 ird taxable income people by band $98,001 - $99,000 (parked)" }, "filter": "taxable_income_band_row_108_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_109", @@ -30849,14 +31254,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30871,7 +31280,7 @@ "target_label": "TY2026-27 ird taxable income people by band $99,001 - $100,000 (parked)" }, "filter": "taxable_income_band_row_109_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_110", @@ -30901,14 +31310,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30923,7 +31336,7 @@ "target_label": "TY2026-27 ird taxable income people by band $100,001 - $101,000 (parked)" }, "filter": "taxable_income_band_row_110_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_111", @@ -30953,14 +31366,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -30975,7 +31392,7 @@ "target_label": "TY2026-27 ird taxable income people by band $101,001 - $102,000 (parked)" }, "filter": "taxable_income_band_row_111_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_112", @@ -31005,14 +31422,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31027,7 +31448,7 @@ "target_label": "TY2026-27 ird taxable income people by band $102,001 - $103,000 (parked)" }, "filter": "taxable_income_band_row_112_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_113", @@ -31057,14 +31478,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31079,7 +31504,7 @@ "target_label": "TY2026-27 ird taxable income people by band $103,001 - $104,000 (parked)" }, "filter": "taxable_income_band_row_113_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_114", @@ -31109,14 +31534,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31131,7 +31560,7 @@ "target_label": "TY2026-27 ird taxable income people by band $104,001 - $105,000 (parked)" }, "filter": "taxable_income_band_row_114_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_115", @@ -31161,14 +31590,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31183,7 +31616,7 @@ "target_label": "TY2026-27 ird taxable income people by band $105,001 - $106,000 (parked)" }, "filter": "taxable_income_band_row_115_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_116", @@ -31213,14 +31646,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31235,7 +31672,7 @@ "target_label": "TY2026-27 ird taxable income people by band $106,001 - $107,000 (parked)" }, "filter": "taxable_income_band_row_116_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_117", @@ -31265,14 +31702,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31287,7 +31728,7 @@ "target_label": "TY2026-27 ird taxable income people by band $107,001 - $108,000 (parked)" }, "filter": "taxable_income_band_row_117_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_118", @@ -31317,14 +31758,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31339,7 +31784,7 @@ "target_label": "TY2026-27 ird taxable income people by band $108,001 - $109,000 (parked)" }, "filter": "taxable_income_band_row_118_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_119", @@ -31369,14 +31814,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31391,7 +31840,7 @@ "target_label": "TY2026-27 ird taxable income people by band $109,001 - $110,000 (parked)" }, "filter": "taxable_income_band_row_119_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_120", @@ -31421,14 +31870,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31443,7 +31896,7 @@ "target_label": "TY2026-27 ird taxable income people by band $110,001 - $111,000 (parked)" }, "filter": "taxable_income_band_row_120_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_121", @@ -31473,14 +31926,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31495,7 +31952,7 @@ "target_label": "TY2026-27 ird taxable income people by band $111,001 - $112,000 (parked)" }, "filter": "taxable_income_band_row_121_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_122", @@ -31525,14 +31982,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31547,7 +32008,7 @@ "target_label": "TY2026-27 ird taxable income people by band $112,001 - $113,000 (parked)" }, "filter": "taxable_income_band_row_122_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_123", @@ -31577,14 +32038,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31599,7 +32064,7 @@ "target_label": "TY2026-27 ird taxable income people by band $113,001 - $114,000 (parked)" }, "filter": "taxable_income_band_row_123_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_124", @@ -31629,14 +32094,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31651,7 +32120,7 @@ "target_label": "TY2026-27 ird taxable income people by band $114,001 - $115,000 (parked)" }, "filter": "taxable_income_band_row_124_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_125", @@ -31681,14 +32150,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31703,7 +32176,7 @@ "target_label": "TY2026-27 ird taxable income people by band $115,001 - $116,000 (parked)" }, "filter": "taxable_income_band_row_125_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_126", @@ -31733,14 +32206,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31755,7 +32232,7 @@ "target_label": "TY2026-27 ird taxable income people by band $116,001 - $117,000 (parked)" }, "filter": "taxable_income_band_row_126_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_127", @@ -31785,14 +32262,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31807,7 +32288,7 @@ "target_label": "TY2026-27 ird taxable income people by band $117,001 - $118,000 (parked)" }, "filter": "taxable_income_band_row_127_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_128", @@ -31837,14 +32318,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31859,7 +32344,7 @@ "target_label": "TY2026-27 ird taxable income people by band $118,001 - $119,000 (parked)" }, "filter": "taxable_income_band_row_128_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_129", @@ -31889,14 +32374,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31911,7 +32400,7 @@ "target_label": "TY2026-27 ird taxable income people by band $119,001 - $120,000 (parked)" }, "filter": "taxable_income_band_row_129_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_130", @@ -31941,14 +32430,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -31963,7 +32456,7 @@ "target_label": "TY2026-27 ird taxable income people by band $120,001 - $121,000 (parked)" }, "filter": "taxable_income_band_row_130_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_131", @@ -31993,14 +32486,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32015,7 +32512,7 @@ "target_label": "TY2026-27 ird taxable income people by band $121,001 - $122,000 (parked)" }, "filter": "taxable_income_band_row_131_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_132", @@ -32045,14 +32542,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32067,7 +32568,7 @@ "target_label": "TY2026-27 ird taxable income people by band $122,001 - $123,000 (parked)" }, "filter": "taxable_income_band_row_132_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_133", @@ -32097,14 +32598,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32119,7 +32624,7 @@ "target_label": "TY2026-27 ird taxable income people by band $123,001 - $124,000 (parked)" }, "filter": "taxable_income_band_row_133_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_134", @@ -32149,14 +32654,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32171,7 +32680,7 @@ "target_label": "TY2026-27 ird taxable income people by band $124,001 - $125,000 (parked)" }, "filter": "taxable_income_band_row_134_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_135", @@ -32201,14 +32710,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32223,7 +32736,7 @@ "target_label": "TY2026-27 ird taxable income people by band $125,001 - $126,000 (parked)" }, "filter": "taxable_income_band_row_135_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_136", @@ -32253,14 +32766,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32275,7 +32792,7 @@ "target_label": "TY2026-27 ird taxable income people by band $126,001 - $127,000 (parked)" }, "filter": "taxable_income_band_row_136_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_137", @@ -32305,14 +32822,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32327,7 +32848,7 @@ "target_label": "TY2026-27 ird taxable income people by band $127,001 - $128,000 (parked)" }, "filter": "taxable_income_band_row_137_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_138", @@ -32357,14 +32878,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32379,7 +32904,7 @@ "target_label": "TY2026-27 ird taxable income people by band $128,001 - $129,000 (parked)" }, "filter": "taxable_income_band_row_138_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_139", @@ -32409,14 +32934,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32431,7 +32960,7 @@ "target_label": "TY2026-27 ird taxable income people by band $129,001 - $130,000 (parked)" }, "filter": "taxable_income_band_row_139_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_140", @@ -32461,14 +32990,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32483,7 +33016,7 @@ "target_label": "TY2026-27 ird taxable income people by band $130,001 - $131,000 (parked)" }, "filter": "taxable_income_band_row_140_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_141", @@ -32513,14 +33046,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32535,7 +33072,7 @@ "target_label": "TY2026-27 ird taxable income people by band $131,001 - $132,000 (parked)" }, "filter": "taxable_income_band_row_141_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_142", @@ -32565,14 +33102,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32587,7 +33128,7 @@ "target_label": "TY2026-27 ird taxable income people by band $132,001 - $133,000 (parked)" }, "filter": "taxable_income_band_row_142_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_143", @@ -32617,14 +33158,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32639,7 +33184,7 @@ "target_label": "TY2026-27 ird taxable income people by band $133,001 - $134,000 (parked)" }, "filter": "taxable_income_band_row_143_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_144", @@ -32669,14 +33214,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32691,7 +33240,7 @@ "target_label": "TY2026-27 ird taxable income people by band $134,001 - $135,000 (parked)" }, "filter": "taxable_income_band_row_144_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_145", @@ -32721,14 +33270,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32743,7 +33296,7 @@ "target_label": "TY2026-27 ird taxable income people by band $135,001 - $136,000 (parked)" }, "filter": "taxable_income_band_row_145_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_146", @@ -32773,14 +33326,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32795,7 +33352,7 @@ "target_label": "TY2026-27 ird taxable income people by band $136,001 - $137,000 (parked)" }, "filter": "taxable_income_band_row_146_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_147", @@ -32825,14 +33382,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32847,7 +33408,7 @@ "target_label": "TY2026-27 ird taxable income people by band $137,001 - $138,000 (parked)" }, "filter": "taxable_income_band_row_147_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_148", @@ -32877,14 +33438,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32899,7 +33464,7 @@ "target_label": "TY2026-27 ird taxable income people by band $138,001 - $139,000 (parked)" }, "filter": "taxable_income_band_row_148_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_149", @@ -32929,14 +33494,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -32951,7 +33520,7 @@ "target_label": "TY2026-27 ird taxable income people by band $139,001 - $140,000 (parked)" }, "filter": "taxable_income_band_row_149_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_150", @@ -32981,14 +33550,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33003,7 +33576,7 @@ "target_label": "TY2026-27 ird taxable income people by band $140,001 - $141,000 (parked)" }, "filter": "taxable_income_band_row_150_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_151", @@ -33033,14 +33606,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33055,7 +33632,7 @@ "target_label": "TY2026-27 ird taxable income people by band $141,001 - $142,000 (parked)" }, "filter": "taxable_income_band_row_151_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_152", @@ -33085,14 +33662,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33107,7 +33688,7 @@ "target_label": "TY2026-27 ird taxable income people by band $142,001 - $143,000 (parked)" }, "filter": "taxable_income_band_row_152_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_153", @@ -33137,14 +33718,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33159,7 +33744,7 @@ "target_label": "TY2026-27 ird taxable income people by band $143,001 - $144,000 (parked)" }, "filter": "taxable_income_band_row_153_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_154", @@ -33189,14 +33774,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33211,7 +33800,7 @@ "target_label": "TY2026-27 ird taxable income people by band $144,001 - $145,000 (parked)" }, "filter": "taxable_income_band_row_154_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_155", @@ -33241,14 +33830,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33263,7 +33856,7 @@ "target_label": "TY2026-27 ird taxable income people by band $145,001 - $146,000 (parked)" }, "filter": "taxable_income_band_row_155_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_156", @@ -33293,14 +33886,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33315,7 +33912,7 @@ "target_label": "TY2026-27 ird taxable income people by band $146,001 - $147,000 (parked)" }, "filter": "taxable_income_band_row_156_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_157", @@ -33345,14 +33942,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33367,7 +33968,7 @@ "target_label": "TY2026-27 ird taxable income people by band $147,001 - $148,000 (parked)" }, "filter": "taxable_income_band_row_157_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_158", @@ -33397,14 +33998,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33419,7 +34024,7 @@ "target_label": "TY2026-27 ird taxable income people by band $148,001 - $149,000 (parked)" }, "filter": "taxable_income_band_row_158_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_159", @@ -33449,14 +34054,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33471,7 +34080,7 @@ "target_label": "TY2026-27 ird taxable income people by band $149,001 - $150,000 (parked)" }, "filter": "taxable_income_band_row_159_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_160", @@ -33501,14 +34110,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33523,7 +34136,7 @@ "target_label": "TY2026-27 ird taxable income people by band $150,001 - $151,000 (parked)" }, "filter": "taxable_income_band_row_160_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_161", @@ -33553,14 +34166,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33575,7 +34192,7 @@ "target_label": "TY2026-27 ird taxable income people by band $151,001 - $152,000 (parked)" }, "filter": "taxable_income_band_row_161_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_162", @@ -33605,14 +34222,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33627,7 +34248,7 @@ "target_label": "TY2026-27 ird taxable income people by band $152,001 - $153,000 (parked)" }, "filter": "taxable_income_band_row_162_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_163", @@ -33657,14 +34278,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33679,7 +34304,7 @@ "target_label": "TY2026-27 ird taxable income people by band $153,001 - $154,000 (parked)" }, "filter": "taxable_income_band_row_163_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_164", @@ -33709,14 +34334,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33731,7 +34360,7 @@ "target_label": "TY2026-27 ird taxable income people by band $154,001 - $155,000 (parked)" }, "filter": "taxable_income_band_row_164_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_165", @@ -33761,14 +34390,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33783,7 +34416,7 @@ "target_label": "TY2026-27 ird taxable income people by band $155,001 - $156,000 (parked)" }, "filter": "taxable_income_band_row_165_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_166", @@ -33813,14 +34446,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33835,7 +34472,7 @@ "target_label": "TY2026-27 ird taxable income people by band $156,001 - $157,000 (parked)" }, "filter": "taxable_income_band_row_166_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_167", @@ -33865,14 +34502,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33887,7 +34528,7 @@ "target_label": "TY2026-27 ird taxable income people by band $157,001 - $158,000 (parked)" }, "filter": "taxable_income_band_row_167_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_168", @@ -33917,14 +34558,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33939,7 +34584,7 @@ "target_label": "TY2026-27 ird taxable income people by band $158,001 - $159,000 (parked)" }, "filter": "taxable_income_band_row_168_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_169", @@ -33969,14 +34614,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -33991,7 +34640,7 @@ "target_label": "TY2026-27 ird taxable income people by band $159,001 - $160,000 (parked)" }, "filter": "taxable_income_band_row_169_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_170", @@ -34021,14 +34670,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34043,7 +34696,7 @@ "target_label": "TY2026-27 ird taxable income people by band $160,001 - $161,000 (parked)" }, "filter": "taxable_income_band_row_170_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_171", @@ -34073,14 +34726,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34095,7 +34752,7 @@ "target_label": "TY2026-27 ird taxable income people by band $161,001 - $162,000 (parked)" }, "filter": "taxable_income_band_row_171_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_172", @@ -34125,14 +34782,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34147,7 +34808,7 @@ "target_label": "TY2026-27 ird taxable income people by band $162,001 - $163,000 (parked)" }, "filter": "taxable_income_band_row_172_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_173", @@ -34177,14 +34838,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34199,7 +34864,7 @@ "target_label": "TY2026-27 ird taxable income people by band $163,001 - $164,000 (parked)" }, "filter": "taxable_income_band_row_173_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_174", @@ -34229,14 +34894,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34251,7 +34920,7 @@ "target_label": "TY2026-27 ird taxable income people by band $164,001 - $165,000 (parked)" }, "filter": "taxable_income_band_row_174_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_175", @@ -34281,14 +34950,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34303,7 +34976,7 @@ "target_label": "TY2026-27 ird taxable income people by band $165,001 - $166,000 (parked)" }, "filter": "taxable_income_band_row_175_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_176", @@ -34333,14 +35006,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34355,7 +35032,7 @@ "target_label": "TY2026-27 ird taxable income people by band $166,001 - $167,000 (parked)" }, "filter": "taxable_income_band_row_176_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_177", @@ -34385,14 +35062,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34407,7 +35088,7 @@ "target_label": "TY2026-27 ird taxable income people by band $167,001 - $168,000 (parked)" }, "filter": "taxable_income_band_row_177_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_178", @@ -34437,14 +35118,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34459,7 +35144,7 @@ "target_label": "TY2026-27 ird taxable income people by band $168,001 - $169,000 (parked)" }, "filter": "taxable_income_band_row_178_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_179", @@ -34489,14 +35174,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34511,7 +35200,7 @@ "target_label": "TY2026-27 ird taxable income people by band $169,001 - $170,000 (parked)" }, "filter": "taxable_income_band_row_179_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_180", @@ -34541,14 +35230,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34563,7 +35256,7 @@ "target_label": "TY2026-27 ird taxable income people by band $170,001 - $171,000 (parked)" }, "filter": "taxable_income_band_row_180_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_181", @@ -34593,14 +35286,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34615,7 +35312,7 @@ "target_label": "TY2026-27 ird taxable income people by band $171,001 - $172,000 (parked)" }, "filter": "taxable_income_band_row_181_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_182", @@ -34645,14 +35342,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34667,7 +35368,7 @@ "target_label": "TY2026-27 ird taxable income people by band $172,001 - $173,000 (parked)" }, "filter": "taxable_income_band_row_182_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_183", @@ -34697,14 +35398,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34719,7 +35424,7 @@ "target_label": "TY2026-27 ird taxable income people by band $173,001 - $174,000 (parked)" }, "filter": "taxable_income_band_row_183_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_184", @@ -34749,14 +35454,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34771,7 +35480,7 @@ "target_label": "TY2026-27 ird taxable income people by band $174,001 - $175,000 (parked)" }, "filter": "taxable_income_band_row_184_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_185", @@ -34801,14 +35510,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34823,7 +35536,7 @@ "target_label": "TY2026-27 ird taxable income people by band $175,001 - $176,000 (parked)" }, "filter": "taxable_income_band_row_185_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_186", @@ -34853,14 +35566,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34875,7 +35592,7 @@ "target_label": "TY2026-27 ird taxable income people by band $176,001 - $177,000 (parked)" }, "filter": "taxable_income_band_row_186_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_187", @@ -34905,14 +35622,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34927,7 +35648,7 @@ "target_label": "TY2026-27 ird taxable income people by band $177,001 - $178,000 (parked)" }, "filter": "taxable_income_band_row_187_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_188", @@ -34957,14 +35678,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -34979,7 +35704,7 @@ "target_label": "TY2026-27 ird taxable income people by band $178,001 - $179,000 (parked)" }, "filter": "taxable_income_band_row_188_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_189", @@ -35009,14 +35734,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35031,7 +35760,7 @@ "target_label": "TY2026-27 ird taxable income people by band $179,001 - $180,000 (parked)" }, "filter": "taxable_income_band_row_189_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_190", @@ -35061,14 +35790,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35083,7 +35816,7 @@ "target_label": "TY2026-27 ird taxable income people by band $180,001 - $181,000 (parked)" }, "filter": "taxable_income_band_row_190_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_191", @@ -35113,14 +35846,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35135,7 +35872,7 @@ "target_label": "TY2026-27 ird taxable income people by band $181,001 - $182,000 (parked)" }, "filter": "taxable_income_band_row_191_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_192", @@ -35165,14 +35902,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35187,7 +35928,7 @@ "target_label": "TY2026-27 ird taxable income people by band $182,001 - $183,000 (parked)" }, "filter": "taxable_income_band_row_192_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_193", @@ -35217,14 +35958,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35239,7 +35984,7 @@ "target_label": "TY2026-27 ird taxable income people by band $183,001 - $184,000 (parked)" }, "filter": "taxable_income_band_row_193_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_194", @@ -35269,14 +36014,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35291,7 +36040,7 @@ "target_label": "TY2026-27 ird taxable income people by band $184,001 - $185,000 (parked)" }, "filter": "taxable_income_band_row_194_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_195", @@ -35321,14 +36070,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35343,7 +36096,7 @@ "target_label": "TY2026-27 ird taxable income people by band $185,001 - $186,000 (parked)" }, "filter": "taxable_income_band_row_195_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_196", @@ -35373,14 +36126,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35395,7 +36152,7 @@ "target_label": "TY2026-27 ird taxable income people by band $186,001 - $187,000 (parked)" }, "filter": "taxable_income_band_row_196_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_197", @@ -35425,14 +36182,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35447,7 +36208,7 @@ "target_label": "TY2026-27 ird taxable income people by band $187,001 - $188,000 (parked)" }, "filter": "taxable_income_band_row_197_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_198", @@ -35477,14 +36238,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35499,7 +36264,7 @@ "target_label": "TY2026-27 ird taxable income people by band $188,001 - $189,000 (parked)" }, "filter": "taxable_income_band_row_198_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_199", @@ -35529,14 +36294,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35551,7 +36320,7 @@ "target_label": "TY2026-27 ird taxable income people by band $189,001 - $190,000 (parked)" }, "filter": "taxable_income_band_row_199_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_200", @@ -35581,14 +36350,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35603,7 +36376,7 @@ "target_label": "TY2026-27 ird taxable income people by band $190,001 - $191,000 (parked)" }, "filter": "taxable_income_band_row_200_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_201", @@ -35633,14 +36406,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35655,7 +36432,7 @@ "target_label": "TY2026-27 ird taxable income people by band $191,001 - $192,000 (parked)" }, "filter": "taxable_income_band_row_201_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_202", @@ -35685,14 +36462,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35707,7 +36488,7 @@ "target_label": "TY2026-27 ird taxable income people by band $192,001 - $193,000 (parked)" }, "filter": "taxable_income_band_row_202_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_203", @@ -35737,14 +36518,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35759,7 +36544,7 @@ "target_label": "TY2026-27 ird taxable income people by band $193,001 - $194,000 (parked)" }, "filter": "taxable_income_band_row_203_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_204", @@ -35789,14 +36574,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35811,7 +36600,7 @@ "target_label": "TY2026-27 ird taxable income people by band $194,001 - $195,000 (parked)" }, "filter": "taxable_income_band_row_204_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_205", @@ -35841,14 +36630,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35863,7 +36656,7 @@ "target_label": "TY2026-27 ird taxable income people by band $195,001 - $196,000 (parked)" }, "filter": "taxable_income_band_row_205_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_206", @@ -35893,14 +36686,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35915,7 +36712,7 @@ "target_label": "TY2026-27 ird taxable income people by band $196,001 - $197,000 (parked)" }, "filter": "taxable_income_band_row_206_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_207", @@ -35945,14 +36742,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -35967,7 +36768,7 @@ "target_label": "TY2026-27 ird taxable income people by band $197,001 - $198,000 (parked)" }, "filter": "taxable_income_band_row_207_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_208", @@ -35997,14 +36798,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36019,7 +36824,7 @@ "target_label": "TY2026-27 ird taxable income people by band $198,001 - $199,000 (parked)" }, "filter": "taxable_income_band_row_208_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_209", @@ -36049,14 +36854,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36071,7 +36880,7 @@ "target_label": "TY2026-27 ird taxable income people by band $199,001 - $200,000 (parked)" }, "filter": "taxable_income_band_row_209_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_210", @@ -36101,14 +36910,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36123,7 +36936,7 @@ "target_label": "TY2026-27 ird taxable income people by band $200,001 - $205,000 (parked)" }, "filter": "taxable_income_band_row_210_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_211", @@ -36153,14 +36966,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36175,7 +36992,7 @@ "target_label": "TY2026-27 ird taxable income people by band $205,001 - $210,000 (parked)" }, "filter": "taxable_income_band_row_211_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_212", @@ -36205,14 +37022,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36227,7 +37048,7 @@ "target_label": "TY2026-27 ird taxable income people by band $210,001 - $215,000 (parked)" }, "filter": "taxable_income_band_row_212_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_213", @@ -36257,14 +37078,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36279,7 +37104,7 @@ "target_label": "TY2026-27 ird taxable income people by band $215,001 - $220,000 (parked)" }, "filter": "taxable_income_band_row_213_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_214", @@ -36309,14 +37134,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36331,7 +37160,7 @@ "target_label": "TY2026-27 ird taxable income people by band $220,001 - $225,000 (parked)" }, "filter": "taxable_income_band_row_214_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_215", @@ -36361,14 +37190,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36383,7 +37216,7 @@ "target_label": "TY2026-27 ird taxable income people by band $225,001 - $230,000 (parked)" }, "filter": "taxable_income_band_row_215_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_216", @@ -36413,14 +37246,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36435,7 +37272,7 @@ "target_label": "TY2026-27 ird taxable income people by band $230,001 - $235,000 (parked)" }, "filter": "taxable_income_band_row_216_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_217", @@ -36465,14 +37302,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36487,7 +37328,7 @@ "target_label": "TY2026-27 ird taxable income people by band $235,001 - $240,000 (parked)" }, "filter": "taxable_income_band_row_217_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_218", @@ -36517,14 +37358,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36539,7 +37384,7 @@ "target_label": "TY2026-27 ird taxable income people by band $240,001 - $245,000 (parked)" }, "filter": "taxable_income_band_row_218_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_219", @@ -36569,14 +37414,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36591,7 +37440,7 @@ "target_label": "TY2026-27 ird taxable income people by band $245,001 - $250,000 (parked)" }, "filter": "taxable_income_band_row_219_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_220", @@ -36621,14 +37470,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36643,7 +37496,7 @@ "target_label": "TY2026-27 ird taxable income people by band $250,001 - $255,000 (parked)" }, "filter": "taxable_income_band_row_220_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_221", @@ -36673,14 +37526,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36695,7 +37552,7 @@ "target_label": "TY2026-27 ird taxable income people by band $255,001 - $260,000 (parked)" }, "filter": "taxable_income_band_row_221_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_222", @@ -36725,14 +37582,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36747,7 +37608,7 @@ "target_label": "TY2026-27 ird taxable income people by band $260,001 - $265,000 (parked)" }, "filter": "taxable_income_band_row_222_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_223", @@ -36777,14 +37638,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36799,7 +37664,7 @@ "target_label": "TY2026-27 ird taxable income people by band $265,001 - $270,000 (parked)" }, "filter": "taxable_income_band_row_223_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_224", @@ -36829,14 +37694,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36851,7 +37720,7 @@ "target_label": "TY2026-27 ird taxable income people by band $270,001 - $275,000 (parked)" }, "filter": "taxable_income_band_row_224_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_225", @@ -36881,14 +37750,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36903,7 +37776,7 @@ "target_label": "TY2026-27 ird taxable income people by band $275,001 - $280,000 (parked)" }, "filter": "taxable_income_band_row_225_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_226", @@ -36933,14 +37806,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -36955,7 +37832,7 @@ "target_label": "TY2026-27 ird taxable income people by band $280,001 - $285,000 (parked)" }, "filter": "taxable_income_band_row_226_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_227", @@ -36985,14 +37862,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37007,7 +37888,7 @@ "target_label": "TY2026-27 ird taxable income people by band $285,001 - $290,000 (parked)" }, "filter": "taxable_income_band_row_227_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_228", @@ -37037,14 +37918,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37059,7 +37944,7 @@ "target_label": "TY2026-27 ird taxable income people by band $290,001 - $295,000 (parked)" }, "filter": "taxable_income_band_row_228_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_229", @@ -37089,14 +37974,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37111,7 +38000,7 @@ "target_label": "TY2026-27 ird taxable income people by band $295,001 - $300,000 (parked)" }, "filter": "taxable_income_band_row_229_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_230", @@ -37141,14 +38030,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37163,7 +38056,7 @@ "target_label": "TY2026-27 ird taxable income people by band $300,000 - $350,000 (parked)" }, "filter": "taxable_income_band_row_230_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_231", @@ -37193,14 +38086,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37215,7 +38112,7 @@ "target_label": "TY2026-27 ird taxable income people by band $350,001 - $400,000 (parked)" }, "filter": "taxable_income_band_row_231_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_232", @@ -37245,14 +38142,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37267,7 +38168,7 @@ "target_label": "TY2026-27 ird taxable income people by band $400,001 - $450,000 (parked)" }, "filter": "taxable_income_band_row_232_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_233", @@ -37297,14 +38198,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37319,7 +38224,7 @@ "target_label": "TY2026-27 ird taxable income people by band $450,001 - $500,000 (parked)" }, "filter": "taxable_income_band_row_233_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_234", @@ -37349,14 +38254,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37371,7 +38280,7 @@ "target_label": "TY2026-27 ird taxable income people by band $500,001 - $550,000 (parked)" }, "filter": "taxable_income_band_row_234_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_235", @@ -37401,14 +38310,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37423,7 +38336,7 @@ "target_label": "TY2026-27 ird taxable income people by band $550,001 - $600,000 (parked)" }, "filter": "taxable_income_band_row_235_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_236", @@ -37453,14 +38366,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37475,7 +38392,7 @@ "target_label": "TY2026-27 ird taxable income people by band $600,001 - $650,000 (parked)" }, "filter": "taxable_income_band_row_236_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_237", @@ -37505,14 +38422,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37527,7 +38448,7 @@ "target_label": "TY2026-27 ird taxable income people by band $650,001 - $700,000 (parked)" }, "filter": "taxable_income_band_row_237_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_238", @@ -37557,14 +38478,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37579,7 +38504,7 @@ "target_label": "TY2026-27 ird taxable income people by band $700,001 - $750,000 (parked)" }, "filter": "taxable_income_band_row_238_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_239", @@ -37609,14 +38534,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37631,7 +38560,7 @@ "target_label": "TY2026-27 ird taxable income people by band $750,001 - $800,000 (parked)" }, "filter": "taxable_income_band_row_239_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_240", @@ -37661,14 +38590,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37683,7 +38616,7 @@ "target_label": "TY2026-27 ird taxable income people by band $800,001 - $850,000 (parked)" }, "filter": "taxable_income_band_row_240_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_241", @@ -37713,14 +38646,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37735,7 +38672,7 @@ "target_label": "TY2026-27 ird taxable income people by band $850,001 - $900,000 (parked)" }, "filter": "taxable_income_band_row_241_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_242", @@ -37765,14 +38702,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37787,7 +38728,7 @@ "target_label": "TY2026-27 ird taxable income people by band $900,001 - $950,000 (parked)" }, "filter": "taxable_income_band_row_242_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_243", @@ -37817,14 +38758,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37839,7 +38784,7 @@ "target_label": "TY2026-27 ird taxable income people by band $950,001 - $1,000,000 (parked)" }, "filter": "taxable_income_band_row_243_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_people_by_band__row_244", @@ -37869,14 +38814,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_people_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "count" }, "hierarchy": { "provider": { @@ -37891,7 +38840,7 @@ "target_label": "TY2026-27 ird taxable income people by band Over $1,000,000 (parked)" }, "filter": "taxable_income_band_row_244_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_8", @@ -37921,14 +38870,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -37943,7 +38896,7 @@ "target_label": "TY2026-27 ird taxable income total by band nil (parked)" }, "filter": "taxable_income_band_row_8_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_9", @@ -37973,14 +38926,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -37995,7 +38952,7 @@ "target_label": "TY2026-27 ird taxable income total by band $0.01 - $100 (parked)" }, "filter": "taxable_income_band_row_9_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_10", @@ -38025,14 +38982,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38047,7 +39008,7 @@ "target_label": "TY2026-27 ird taxable income total by band $101 - $1,000 (parked)" }, "filter": "taxable_income_band_row_10_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_11", @@ -38077,14 +39038,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38099,7 +39064,7 @@ "target_label": "TY2026-27 ird taxable income total by band $1,001 - $2,000 (parked)" }, "filter": "taxable_income_band_row_11_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_12", @@ -38129,14 +39094,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38151,7 +39120,7 @@ "target_label": "TY2026-27 ird taxable income total by band $2,001 - $3,000 (parked)" }, "filter": "taxable_income_band_row_12_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_13", @@ -38181,14 +39150,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38203,7 +39176,7 @@ "target_label": "TY2026-27 ird taxable income total by band $3,001 - $4,000 (parked)" }, "filter": "taxable_income_band_row_13_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_14", @@ -38233,14 +39206,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38255,7 +39232,7 @@ "target_label": "TY2026-27 ird taxable income total by band $4,001 - $5,000 (parked)" }, "filter": "taxable_income_band_row_14_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_15", @@ -38285,14 +39262,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38307,7 +39288,7 @@ "target_label": "TY2026-27 ird taxable income total by band $5,001 - $6,000 (parked)" }, "filter": "taxable_income_band_row_15_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_16", @@ -38337,14 +39318,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38359,7 +39344,7 @@ "target_label": "TY2026-27 ird taxable income total by band $6,001 - $7,000 (parked)" }, "filter": "taxable_income_band_row_16_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_17", @@ -38389,14 +39374,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38411,7 +39400,7 @@ "target_label": "TY2026-27 ird taxable income total by band $7,001 - $8,000 (parked)" }, "filter": "taxable_income_band_row_17_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_18", @@ -38441,14 +39430,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38463,7 +39456,7 @@ "target_label": "TY2026-27 ird taxable income total by band $8,001 - $9,000 (parked)" }, "filter": "taxable_income_band_row_18_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_19", @@ -38493,14 +39486,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38515,7 +39512,7 @@ "target_label": "TY2026-27 ird taxable income total by band $9,001 - $10,000 (parked)" }, "filter": "taxable_income_band_row_19_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_20", @@ -38545,14 +39542,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38567,7 +39568,7 @@ "target_label": "TY2026-27 ird taxable income total by band $10,001 - $11,000 (parked)" }, "filter": "taxable_income_band_row_20_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_21", @@ -38597,14 +39598,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38619,7 +39624,7 @@ "target_label": "TY2026-27 ird taxable income total by band $11,001 - $12,000 (parked)" }, "filter": "taxable_income_band_row_21_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_22", @@ -38649,14 +39654,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38671,7 +39680,7 @@ "target_label": "TY2026-27 ird taxable income total by band $12,001 - $13,000 (parked)" }, "filter": "taxable_income_band_row_22_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_23", @@ -38701,14 +39710,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38723,7 +39736,7 @@ "target_label": "TY2026-27 ird taxable income total by band $13,001 - $14,000 (parked)" }, "filter": "taxable_income_band_row_23_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_24", @@ -38753,14 +39766,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38775,7 +39792,7 @@ "target_label": "TY2026-27 ird taxable income total by band $14,001 - $15,000 (parked)" }, "filter": "taxable_income_band_row_24_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_25", @@ -38805,14 +39822,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38827,7 +39848,7 @@ "target_label": "TY2026-27 ird taxable income total by band $15,001 - $16,000 (parked)" }, "filter": "taxable_income_band_row_25_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_26", @@ -38857,14 +39878,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38879,7 +39904,7 @@ "target_label": "TY2026-27 ird taxable income total by band $16,001 - $17,000 (parked)" }, "filter": "taxable_income_band_row_26_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_27", @@ -38909,14 +39934,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38931,7 +39960,7 @@ "target_label": "TY2026-27 ird taxable income total by band $17,001 - $18,000 (parked)" }, "filter": "taxable_income_band_row_27_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_28", @@ -38961,14 +39990,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -38983,7 +40016,7 @@ "target_label": "TY2026-27 ird taxable income total by band $18,001 - $19,000 (parked)" }, "filter": "taxable_income_band_row_28_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_29", @@ -39013,14 +40046,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39035,7 +40072,7 @@ "target_label": "TY2026-27 ird taxable income total by band $19,001 - $20,000 (parked)" }, "filter": "taxable_income_band_row_29_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_30", @@ -39065,14 +40102,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39087,7 +40128,7 @@ "target_label": "TY2026-27 ird taxable income total by band $20,000 - $21,000 (parked)" }, "filter": "taxable_income_band_row_30_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_31", @@ -39117,14 +40158,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39139,7 +40184,7 @@ "target_label": "TY2026-27 ird taxable income total by band $21,001 - $22,000 (parked)" }, "filter": "taxable_income_band_row_31_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_32", @@ -39169,14 +40214,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39191,7 +40240,7 @@ "target_label": "TY2026-27 ird taxable income total by band $22,001 - $23,000 (parked)" }, "filter": "taxable_income_band_row_32_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_33", @@ -39221,14 +40270,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39243,7 +40296,7 @@ "target_label": "TY2026-27 ird taxable income total by band $23,001 - $24,000 (parked)" }, "filter": "taxable_income_band_row_33_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_34", @@ -39273,14 +40326,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39295,7 +40352,7 @@ "target_label": "TY2026-27 ird taxable income total by band $24,001 - $25,000 (parked)" }, "filter": "taxable_income_band_row_34_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_35", @@ -39325,14 +40382,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39347,7 +40408,7 @@ "target_label": "TY2026-27 ird taxable income total by band $25,001 - $26,000 (parked)" }, "filter": "taxable_income_band_row_35_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_36", @@ -39377,14 +40438,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39399,7 +40464,7 @@ "target_label": "TY2026-27 ird taxable income total by band $26,001 - $27,000 (parked)" }, "filter": "taxable_income_band_row_36_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_37", @@ -39429,14 +40494,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39451,7 +40520,7 @@ "target_label": "TY2026-27 ird taxable income total by band $27,001 - $28,000 (parked)" }, "filter": "taxable_income_band_row_37_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_38", @@ -39481,14 +40550,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39503,7 +40576,7 @@ "target_label": "TY2026-27 ird taxable income total by band $28,001 - $29,000 (parked)" }, "filter": "taxable_income_band_row_38_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_39", @@ -39533,14 +40606,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39555,7 +40632,7 @@ "target_label": "TY2026-27 ird taxable income total by band $29,001 - $30,000 (parked)" }, "filter": "taxable_income_band_row_39_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_40", @@ -39585,14 +40662,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39607,7 +40688,7 @@ "target_label": "TY2026-27 ird taxable income total by band $30,001 - $31,000 (parked)" }, "filter": "taxable_income_band_row_40_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_41", @@ -39637,14 +40718,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39659,7 +40744,7 @@ "target_label": "TY2026-27 ird taxable income total by band $31,001 - $32,000 (parked)" }, "filter": "taxable_income_band_row_41_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_42", @@ -39689,14 +40774,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39711,7 +40800,7 @@ "target_label": "TY2026-27 ird taxable income total by band $32,001 - $33,000 (parked)" }, "filter": "taxable_income_band_row_42_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_43", @@ -39741,14 +40830,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39763,7 +40856,7 @@ "target_label": "TY2026-27 ird taxable income total by band $33,001 - $34,000 (parked)" }, "filter": "taxable_income_band_row_43_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_44", @@ -39793,14 +40886,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39815,7 +40912,7 @@ "target_label": "TY2026-27 ird taxable income total by band $34,001 - $35,000 (parked)" }, "filter": "taxable_income_band_row_44_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_45", @@ -39845,14 +40942,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39867,7 +40968,7 @@ "target_label": "TY2026-27 ird taxable income total by band $35,001 - $36,000 (parked)" }, "filter": "taxable_income_band_row_45_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_46", @@ -39897,14 +40998,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39919,7 +41024,7 @@ "target_label": "TY2026-27 ird taxable income total by band $36,001 - $37,000 (parked)" }, "filter": "taxable_income_band_row_46_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_47", @@ -39949,14 +41054,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -39971,7 +41080,7 @@ "target_label": "TY2026-27 ird taxable income total by band $37,001 - $38,000 (parked)" }, "filter": "taxable_income_band_row_47_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_48", @@ -40001,14 +41110,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40023,7 +41136,7 @@ "target_label": "TY2026-27 ird taxable income total by band $38,001 - $39,000 (parked)" }, "filter": "taxable_income_band_row_48_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_49", @@ -40053,14 +41166,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40075,7 +41192,7 @@ "target_label": "TY2026-27 ird taxable income total by band $39,001 - $40,000 (parked)" }, "filter": "taxable_income_band_row_49_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_50", @@ -40105,14 +41222,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40127,7 +41248,7 @@ "target_label": "TY2026-27 ird taxable income total by band $40,001 - $41,000 (parked)" }, "filter": "taxable_income_band_row_50_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_51", @@ -40157,14 +41278,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40179,7 +41304,7 @@ "target_label": "TY2026-27 ird taxable income total by band $41,001 - $42,000 (parked)" }, "filter": "taxable_income_band_row_51_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_52", @@ -40209,14 +41334,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40231,7 +41360,7 @@ "target_label": "TY2026-27 ird taxable income total by band $42,001 - $43,000 (parked)" }, "filter": "taxable_income_band_row_52_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_53", @@ -40261,14 +41390,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40283,7 +41416,7 @@ "target_label": "TY2026-27 ird taxable income total by band $43,001 - $44,000 (parked)" }, "filter": "taxable_income_band_row_53_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_54", @@ -40313,14 +41446,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40335,7 +41472,7 @@ "target_label": "TY2026-27 ird taxable income total by band $44,001 - $45,000 (parked)" }, "filter": "taxable_income_band_row_54_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_55", @@ -40365,14 +41502,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40387,7 +41528,7 @@ "target_label": "TY2026-27 ird taxable income total by band $45,001 - $46,000 (parked)" }, "filter": "taxable_income_band_row_55_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_56", @@ -40417,14 +41558,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40439,7 +41584,7 @@ "target_label": "TY2026-27 ird taxable income total by band $46,001 - $47,000 (parked)" }, "filter": "taxable_income_band_row_56_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_57", @@ -40469,14 +41614,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40491,7 +41640,7 @@ "target_label": "TY2026-27 ird taxable income total by band $47,001 - $48,000 (parked)" }, "filter": "taxable_income_band_row_57_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_58", @@ -40521,14 +41670,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40543,7 +41696,7 @@ "target_label": "TY2026-27 ird taxable income total by band $48,001 - $49,000 (parked)" }, "filter": "taxable_income_band_row_58_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_59", @@ -40573,14 +41726,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40595,7 +41752,7 @@ "target_label": "TY2026-27 ird taxable income total by band $49,001 - $50,000 (parked)" }, "filter": "taxable_income_band_row_59_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_60", @@ -40625,14 +41782,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40647,7 +41808,7 @@ "target_label": "TY2026-27 ird taxable income total by band $50,000 - $51,000 (parked)" }, "filter": "taxable_income_band_row_60_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_61", @@ -40677,14 +41838,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40699,7 +41864,7 @@ "target_label": "TY2026-27 ird taxable income total by band $51,001 - $52,000 (parked)" }, "filter": "taxable_income_band_row_61_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_62", @@ -40729,14 +41894,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40751,7 +41920,7 @@ "target_label": "TY2026-27 ird taxable income total by band $52,001 - $53,000 (parked)" }, "filter": "taxable_income_band_row_62_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_63", @@ -40781,14 +41950,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40803,7 +41976,7 @@ "target_label": "TY2026-27 ird taxable income total by band $53,001 - $54,000 (parked)" }, "filter": "taxable_income_band_row_63_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_64", @@ -40833,14 +42006,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40855,7 +42032,7 @@ "target_label": "TY2026-27 ird taxable income total by band $54,001 - $55,000 (parked)" }, "filter": "taxable_income_band_row_64_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_65", @@ -40885,14 +42062,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40907,7 +42088,7 @@ "target_label": "TY2026-27 ird taxable income total by band $55,001 - $56,000 (parked)" }, "filter": "taxable_income_band_row_65_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_66", @@ -40937,14 +42118,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -40959,7 +42144,7 @@ "target_label": "TY2026-27 ird taxable income total by band $56,001 - $57,000 (parked)" }, "filter": "taxable_income_band_row_66_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_67", @@ -40989,14 +42174,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41011,7 +42200,7 @@ "target_label": "TY2026-27 ird taxable income total by band $57,001 - $58,000 (parked)" }, "filter": "taxable_income_band_row_67_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_68", @@ -41041,14 +42230,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41063,7 +42256,7 @@ "target_label": "TY2026-27 ird taxable income total by band $58,001 - $59,000 (parked)" }, "filter": "taxable_income_band_row_68_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_69", @@ -41093,14 +42286,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41115,7 +42312,7 @@ "target_label": "TY2026-27 ird taxable income total by band $59,001 - $60,000 (parked)" }, "filter": "taxable_income_band_row_69_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_70", @@ -41145,14 +42342,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41167,7 +42368,7 @@ "target_label": "TY2026-27 ird taxable income total by band $60,001 - $61,000 (parked)" }, "filter": "taxable_income_band_row_70_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_71", @@ -41197,14 +42398,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41219,7 +42424,7 @@ "target_label": "TY2026-27 ird taxable income total by band $61,001 - $62,000 (parked)" }, "filter": "taxable_income_band_row_71_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_72", @@ -41249,14 +42454,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41271,7 +42480,7 @@ "target_label": "TY2026-27 ird taxable income total by band $62,001 - $63,000 (parked)" }, "filter": "taxable_income_band_row_72_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_73", @@ -41301,14 +42510,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41323,7 +42536,7 @@ "target_label": "TY2026-27 ird taxable income total by band $63,001 - $64,000 (parked)" }, "filter": "taxable_income_band_row_73_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_74", @@ -41353,14 +42566,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41375,7 +42592,7 @@ "target_label": "TY2026-27 ird taxable income total by band $64,001 - $65,000 (parked)" }, "filter": "taxable_income_band_row_74_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_75", @@ -41405,14 +42622,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41427,7 +42648,7 @@ "target_label": "TY2026-27 ird taxable income total by band $65,001 - $66,000 (parked)" }, "filter": "taxable_income_band_row_75_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_76", @@ -41457,14 +42678,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41479,7 +42704,7 @@ "target_label": "TY2026-27 ird taxable income total by band $66,001 - $67,000 (parked)" }, "filter": "taxable_income_band_row_76_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_77", @@ -41509,14 +42734,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41531,7 +42760,7 @@ "target_label": "TY2026-27 ird taxable income total by band $67,001 - $68,000 (parked)" }, "filter": "taxable_income_band_row_77_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_78", @@ -41561,14 +42790,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41583,7 +42816,7 @@ "target_label": "TY2026-27 ird taxable income total by band $68,001 - $69,000 (parked)" }, "filter": "taxable_income_band_row_78_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_79", @@ -41613,14 +42846,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41635,7 +42872,7 @@ "target_label": "TY2026-27 ird taxable income total by band $69,001 - $70,000 (parked)" }, "filter": "taxable_income_band_row_79_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_80", @@ -41665,14 +42902,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41687,7 +42928,7 @@ "target_label": "TY2026-27 ird taxable income total by band $70,001 - $71,000 (parked)" }, "filter": "taxable_income_band_row_80_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_81", @@ -41717,14 +42958,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41739,7 +42984,7 @@ "target_label": "TY2026-27 ird taxable income total by band $71,001 - $72,000 (parked)" }, "filter": "taxable_income_band_row_81_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_82", @@ -41769,14 +43014,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41791,7 +43040,7 @@ "target_label": "TY2026-27 ird taxable income total by band $72,001 - $73,000 (parked)" }, "filter": "taxable_income_band_row_82_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_83", @@ -41821,14 +43070,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41843,7 +43096,7 @@ "target_label": "TY2026-27 ird taxable income total by band $73,001 - $74,000 (parked)" }, "filter": "taxable_income_band_row_83_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_84", @@ -41873,14 +43126,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41895,7 +43152,7 @@ "target_label": "TY2026-27 ird taxable income total by band $74,001 - $75,000 (parked)" }, "filter": "taxable_income_band_row_84_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_85", @@ -41925,14 +43182,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41947,7 +43208,7 @@ "target_label": "TY2026-27 ird taxable income total by band $75,001 - $76,000 (parked)" }, "filter": "taxable_income_band_row_85_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_86", @@ -41977,14 +43238,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -41999,7 +43264,7 @@ "target_label": "TY2026-27 ird taxable income total by band $76,001 - $77,000 (parked)" }, "filter": "taxable_income_band_row_86_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_87", @@ -42029,14 +43294,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42051,7 +43320,7 @@ "target_label": "TY2026-27 ird taxable income total by band $77,001 - $78,000 (parked)" }, "filter": "taxable_income_band_row_87_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_88", @@ -42081,14 +43350,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42103,7 +43376,7 @@ "target_label": "TY2026-27 ird taxable income total by band $78,001 - $79,000 (parked)" }, "filter": "taxable_income_band_row_88_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_89", @@ -42133,14 +43406,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42155,7 +43432,7 @@ "target_label": "TY2026-27 ird taxable income total by band $79,001 - $80,000 (parked)" }, "filter": "taxable_income_band_row_89_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_90", @@ -42185,14 +43462,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42207,7 +43488,7 @@ "target_label": "TY2026-27 ird taxable income total by band $80,000 - $81,000 (parked)" }, "filter": "taxable_income_band_row_90_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_91", @@ -42237,14 +43518,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42259,7 +43544,7 @@ "target_label": "TY2026-27 ird taxable income total by band $81,001 - $82,000 (parked)" }, "filter": "taxable_income_band_row_91_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_92", @@ -42289,14 +43574,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42311,7 +43600,7 @@ "target_label": "TY2026-27 ird taxable income total by band $82,001 - $83,000 (parked)" }, "filter": "taxable_income_band_row_92_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_93", @@ -42341,14 +43630,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42363,7 +43656,7 @@ "target_label": "TY2026-27 ird taxable income total by band $83,001 - $84,000 (parked)" }, "filter": "taxable_income_band_row_93_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_94", @@ -42393,14 +43686,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42415,7 +43712,7 @@ "target_label": "TY2026-27 ird taxable income total by band $84,001 - $85,000 (parked)" }, "filter": "taxable_income_band_row_94_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_95", @@ -42445,14 +43742,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42467,7 +43768,7 @@ "target_label": "TY2026-27 ird taxable income total by band $85,001 - $86,000 (parked)" }, "filter": "taxable_income_band_row_95_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_96", @@ -42497,14 +43798,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42519,7 +43824,7 @@ "target_label": "TY2026-27 ird taxable income total by band $86,001 - $87,000 (parked)" }, "filter": "taxable_income_band_row_96_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_97", @@ -42549,14 +43854,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42571,7 +43880,7 @@ "target_label": "TY2026-27 ird taxable income total by band $87,001 - $88,000 (parked)" }, "filter": "taxable_income_band_row_97_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_98", @@ -42601,14 +43910,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42623,7 +43936,7 @@ "target_label": "TY2026-27 ird taxable income total by band $88,001 - $89,000 (parked)" }, "filter": "taxable_income_band_row_98_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_99", @@ -42653,14 +43966,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42675,7 +43992,7 @@ "target_label": "TY2026-27 ird taxable income total by band $89,001 - $90,000 (parked)" }, "filter": "taxable_income_band_row_99_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_100", @@ -42705,14 +44022,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42727,7 +44048,7 @@ "target_label": "TY2026-27 ird taxable income total by band $90,001 - $91,000 (parked)" }, "filter": "taxable_income_band_row_100_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_101", @@ -42757,14 +44078,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42779,7 +44104,7 @@ "target_label": "TY2026-27 ird taxable income total by band $91,001 - $92,000 (parked)" }, "filter": "taxable_income_band_row_101_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_102", @@ -42809,14 +44134,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42831,7 +44160,7 @@ "target_label": "TY2026-27 ird taxable income total by band $92,001 - $93,000 (parked)" }, "filter": "taxable_income_band_row_102_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_103", @@ -42861,14 +44190,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42883,7 +44216,7 @@ "target_label": "TY2026-27 ird taxable income total by band $93,001 - $94,000 (parked)" }, "filter": "taxable_income_band_row_103_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_104", @@ -42913,14 +44246,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42935,7 +44272,7 @@ "target_label": "TY2026-27 ird taxable income total by band $94,001 - $95,000 (parked)" }, "filter": "taxable_income_band_row_104_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_105", @@ -42965,14 +44302,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -42987,7 +44328,7 @@ "target_label": "TY2026-27 ird taxable income total by band $95,001 - $96,000 (parked)" }, "filter": "taxable_income_band_row_105_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_106", @@ -43017,14 +44358,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43039,7 +44384,7 @@ "target_label": "TY2026-27 ird taxable income total by band $96,001 - $97,000 (parked)" }, "filter": "taxable_income_band_row_106_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_107", @@ -43069,14 +44414,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43091,7 +44440,7 @@ "target_label": "TY2026-27 ird taxable income total by band $97,001 - $98,000 (parked)" }, "filter": "taxable_income_band_row_107_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_108", @@ -43121,14 +44470,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43143,7 +44496,7 @@ "target_label": "TY2026-27 ird taxable income total by band $98,001 - $99,000 (parked)" }, "filter": "taxable_income_band_row_108_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_109", @@ -43173,14 +44526,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43195,7 +44552,7 @@ "target_label": "TY2026-27 ird taxable income total by band $99,001 - $100,000 (parked)" }, "filter": "taxable_income_band_row_109_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_110", @@ -43225,14 +44582,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43247,7 +44608,7 @@ "target_label": "TY2026-27 ird taxable income total by band $100,001 - $101,000 (parked)" }, "filter": "taxable_income_band_row_110_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_111", @@ -43277,14 +44638,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43299,7 +44664,7 @@ "target_label": "TY2026-27 ird taxable income total by band $101,001 - $102,000 (parked)" }, "filter": "taxable_income_band_row_111_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_112", @@ -43329,14 +44694,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43351,7 +44720,7 @@ "target_label": "TY2026-27 ird taxable income total by band $102,001 - $103,000 (parked)" }, "filter": "taxable_income_band_row_112_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_113", @@ -43381,14 +44750,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43403,7 +44776,7 @@ "target_label": "TY2026-27 ird taxable income total by band $103,001 - $104,000 (parked)" }, "filter": "taxable_income_band_row_113_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_114", @@ -43433,14 +44806,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43455,7 +44832,7 @@ "target_label": "TY2026-27 ird taxable income total by band $104,001 - $105,000 (parked)" }, "filter": "taxable_income_band_row_114_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_115", @@ -43485,14 +44862,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43507,7 +44888,7 @@ "target_label": "TY2026-27 ird taxable income total by band $105,001 - $106,000 (parked)" }, "filter": "taxable_income_band_row_115_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_116", @@ -43537,14 +44918,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43559,7 +44944,7 @@ "target_label": "TY2026-27 ird taxable income total by band $106,001 - $107,000 (parked)" }, "filter": "taxable_income_band_row_116_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_117", @@ -43589,14 +44974,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43611,7 +45000,7 @@ "target_label": "TY2026-27 ird taxable income total by band $107,001 - $108,000 (parked)" }, "filter": "taxable_income_band_row_117_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_118", @@ -43641,14 +45030,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43663,7 +45056,7 @@ "target_label": "TY2026-27 ird taxable income total by band $108,001 - $109,000 (parked)" }, "filter": "taxable_income_band_row_118_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_119", @@ -43693,14 +45086,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43715,7 +45112,7 @@ "target_label": "TY2026-27 ird taxable income total by band $109,001 - $110,000 (parked)" }, "filter": "taxable_income_band_row_119_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_120", @@ -43745,14 +45142,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43767,7 +45168,7 @@ "target_label": "TY2026-27 ird taxable income total by band $110,001 - $111,000 (parked)" }, "filter": "taxable_income_band_row_120_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_121", @@ -43797,14 +45198,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43819,7 +45224,7 @@ "target_label": "TY2026-27 ird taxable income total by band $111,001 - $112,000 (parked)" }, "filter": "taxable_income_band_row_121_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_122", @@ -43849,14 +45254,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43871,7 +45280,7 @@ "target_label": "TY2026-27 ird taxable income total by band $112,001 - $113,000 (parked)" }, "filter": "taxable_income_band_row_122_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_123", @@ -43901,14 +45310,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43923,7 +45336,7 @@ "target_label": "TY2026-27 ird taxable income total by band $113,001 - $114,000 (parked)" }, "filter": "taxable_income_band_row_123_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_124", @@ -43953,14 +45366,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -43975,7 +45392,7 @@ "target_label": "TY2026-27 ird taxable income total by band $114,001 - $115,000 (parked)" }, "filter": "taxable_income_band_row_124_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_125", @@ -44005,14 +45422,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44027,7 +45448,7 @@ "target_label": "TY2026-27 ird taxable income total by band $115,001 - $116,000 (parked)" }, "filter": "taxable_income_band_row_125_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_126", @@ -44057,14 +45478,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44079,7 +45504,7 @@ "target_label": "TY2026-27 ird taxable income total by band $116,001 - $117,000 (parked)" }, "filter": "taxable_income_band_row_126_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_127", @@ -44109,14 +45534,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44131,7 +45560,7 @@ "target_label": "TY2026-27 ird taxable income total by band $117,001 - $118,000 (parked)" }, "filter": "taxable_income_band_row_127_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_128", @@ -44161,14 +45590,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44183,7 +45616,7 @@ "target_label": "TY2026-27 ird taxable income total by band $118,001 - $119,000 (parked)" }, "filter": "taxable_income_band_row_128_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_129", @@ -44213,14 +45646,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44235,7 +45672,7 @@ "target_label": "TY2026-27 ird taxable income total by band $119,001 - $120,000 (parked)" }, "filter": "taxable_income_band_row_129_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_130", @@ -44265,14 +45702,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44287,7 +45728,7 @@ "target_label": "TY2026-27 ird taxable income total by band $120,001 - $121,000 (parked)" }, "filter": "taxable_income_band_row_130_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_131", @@ -44317,14 +45758,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44339,7 +45784,7 @@ "target_label": "TY2026-27 ird taxable income total by band $121,001 - $122,000 (parked)" }, "filter": "taxable_income_band_row_131_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_132", @@ -44369,14 +45814,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44391,7 +45840,7 @@ "target_label": "TY2026-27 ird taxable income total by band $122,001 - $123,000 (parked)" }, "filter": "taxable_income_band_row_132_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_133", @@ -44421,14 +45870,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44443,7 +45896,7 @@ "target_label": "TY2026-27 ird taxable income total by band $123,001 - $124,000 (parked)" }, "filter": "taxable_income_band_row_133_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_134", @@ -44473,14 +45926,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44495,7 +45952,7 @@ "target_label": "TY2026-27 ird taxable income total by band $124,001 - $125,000 (parked)" }, "filter": "taxable_income_band_row_134_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_135", @@ -44525,14 +45982,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44547,7 +46008,7 @@ "target_label": "TY2026-27 ird taxable income total by band $125,001 - $126,000 (parked)" }, "filter": "taxable_income_band_row_135_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_136", @@ -44577,14 +46038,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44599,7 +46064,7 @@ "target_label": "TY2026-27 ird taxable income total by band $126,001 - $127,000 (parked)" }, "filter": "taxable_income_band_row_136_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_137", @@ -44629,14 +46094,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44651,7 +46120,7 @@ "target_label": "TY2026-27 ird taxable income total by band $127,001 - $128,000 (parked)" }, "filter": "taxable_income_band_row_137_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_138", @@ -44681,14 +46150,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44703,7 +46176,7 @@ "target_label": "TY2026-27 ird taxable income total by band $128,001 - $129,000 (parked)" }, "filter": "taxable_income_band_row_138_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_139", @@ -44733,14 +46206,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44755,7 +46232,7 @@ "target_label": "TY2026-27 ird taxable income total by band $129,001 - $130,000 (parked)" }, "filter": "taxable_income_band_row_139_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_140", @@ -44785,14 +46262,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44807,7 +46288,7 @@ "target_label": "TY2026-27 ird taxable income total by band $130,001 - $131,000 (parked)" }, "filter": "taxable_income_band_row_140_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_141", @@ -44837,14 +46318,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44859,7 +46344,7 @@ "target_label": "TY2026-27 ird taxable income total by band $131,001 - $132,000 (parked)" }, "filter": "taxable_income_band_row_141_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_142", @@ -44889,14 +46374,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44911,7 +46400,7 @@ "target_label": "TY2026-27 ird taxable income total by band $132,001 - $133,000 (parked)" }, "filter": "taxable_income_band_row_142_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_143", @@ -44941,14 +46430,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -44963,7 +46456,7 @@ "target_label": "TY2026-27 ird taxable income total by band $133,001 - $134,000 (parked)" }, "filter": "taxable_income_band_row_143_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_144", @@ -44993,14 +46486,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45015,7 +46512,7 @@ "target_label": "TY2026-27 ird taxable income total by band $134,001 - $135,000 (parked)" }, "filter": "taxable_income_band_row_144_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_145", @@ -45045,14 +46542,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45067,7 +46568,7 @@ "target_label": "TY2026-27 ird taxable income total by band $135,001 - $136,000 (parked)" }, "filter": "taxable_income_band_row_145_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_146", @@ -45097,14 +46598,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45119,7 +46624,7 @@ "target_label": "TY2026-27 ird taxable income total by band $136,001 - $137,000 (parked)" }, "filter": "taxable_income_band_row_146_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_147", @@ -45149,14 +46654,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45171,7 +46680,7 @@ "target_label": "TY2026-27 ird taxable income total by band $137,001 - $138,000 (parked)" }, "filter": "taxable_income_band_row_147_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_148", @@ -45201,14 +46710,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45223,7 +46736,7 @@ "target_label": "TY2026-27 ird taxable income total by band $138,001 - $139,000 (parked)" }, "filter": "taxable_income_band_row_148_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_149", @@ -45253,14 +46766,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45275,7 +46792,7 @@ "target_label": "TY2026-27 ird taxable income total by band $139,001 - $140,000 (parked)" }, "filter": "taxable_income_band_row_149_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_150", @@ -45305,14 +46822,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45327,7 +46848,7 @@ "target_label": "TY2026-27 ird taxable income total by band $140,001 - $141,000 (parked)" }, "filter": "taxable_income_band_row_150_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_151", @@ -45357,14 +46878,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45379,7 +46904,7 @@ "target_label": "TY2026-27 ird taxable income total by band $141,001 - $142,000 (parked)" }, "filter": "taxable_income_band_row_151_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_152", @@ -45409,14 +46934,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45431,7 +46960,7 @@ "target_label": "TY2026-27 ird taxable income total by band $142,001 - $143,000 (parked)" }, "filter": "taxable_income_band_row_152_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_153", @@ -45461,14 +46990,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45483,7 +47016,7 @@ "target_label": "TY2026-27 ird taxable income total by band $143,001 - $144,000 (parked)" }, "filter": "taxable_income_band_row_153_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_154", @@ -45513,14 +47046,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45535,7 +47072,7 @@ "target_label": "TY2026-27 ird taxable income total by band $144,001 - $145,000 (parked)" }, "filter": "taxable_income_band_row_154_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_155", @@ -45565,14 +47102,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45587,7 +47128,7 @@ "target_label": "TY2026-27 ird taxable income total by band $145,001 - $146,000 (parked)" }, "filter": "taxable_income_band_row_155_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_156", @@ -45617,14 +47158,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45639,7 +47184,7 @@ "target_label": "TY2026-27 ird taxable income total by band $146,001 - $147,000 (parked)" }, "filter": "taxable_income_band_row_156_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_157", @@ -45669,14 +47214,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45691,7 +47240,7 @@ "target_label": "TY2026-27 ird taxable income total by band $147,001 - $148,000 (parked)" }, "filter": "taxable_income_band_row_157_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_158", @@ -45721,14 +47270,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45743,7 +47296,7 @@ "target_label": "TY2026-27 ird taxable income total by band $148,001 - $149,000 (parked)" }, "filter": "taxable_income_band_row_158_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_159", @@ -45773,14 +47326,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45795,7 +47352,7 @@ "target_label": "TY2026-27 ird taxable income total by band $149,001 - $150,000 (parked)" }, "filter": "taxable_income_band_row_159_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_160", @@ -45825,14 +47382,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45847,7 +47408,7 @@ "target_label": "TY2026-27 ird taxable income total by band $150,001 - $151,000 (parked)" }, "filter": "taxable_income_band_row_160_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_161", @@ -45877,14 +47438,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45899,7 +47464,7 @@ "target_label": "TY2026-27 ird taxable income total by band $151,001 - $152,000 (parked)" }, "filter": "taxable_income_band_row_161_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_162", @@ -45929,14 +47494,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -45951,7 +47520,7 @@ "target_label": "TY2026-27 ird taxable income total by band $152,001 - $153,000 (parked)" }, "filter": "taxable_income_band_row_162_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_163", @@ -45981,14 +47550,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46003,7 +47576,7 @@ "target_label": "TY2026-27 ird taxable income total by band $153,001 - $154,000 (parked)" }, "filter": "taxable_income_band_row_163_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_164", @@ -46033,14 +47606,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46055,7 +47632,7 @@ "target_label": "TY2026-27 ird taxable income total by band $154,001 - $155,000 (parked)" }, "filter": "taxable_income_band_row_164_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_165", @@ -46085,14 +47662,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46107,7 +47688,7 @@ "target_label": "TY2026-27 ird taxable income total by band $155,001 - $156,000 (parked)" }, "filter": "taxable_income_band_row_165_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_166", @@ -46137,14 +47718,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46159,7 +47744,7 @@ "target_label": "TY2026-27 ird taxable income total by band $156,001 - $157,000 (parked)" }, "filter": "taxable_income_band_row_166_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_167", @@ -46189,14 +47774,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46211,7 +47800,7 @@ "target_label": "TY2026-27 ird taxable income total by band $157,001 - $158,000 (parked)" }, "filter": "taxable_income_band_row_167_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_168", @@ -46241,14 +47830,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46263,7 +47856,7 @@ "target_label": "TY2026-27 ird taxable income total by band $158,001 - $159,000 (parked)" }, "filter": "taxable_income_band_row_168_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_169", @@ -46293,14 +47886,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46315,7 +47912,7 @@ "target_label": "TY2026-27 ird taxable income total by band $159,001 - $160,000 (parked)" }, "filter": "taxable_income_band_row_169_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_170", @@ -46345,14 +47942,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46367,7 +47968,7 @@ "target_label": "TY2026-27 ird taxable income total by band $160,001 - $161,000 (parked)" }, "filter": "taxable_income_band_row_170_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_171", @@ -46397,14 +47998,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46419,7 +48024,7 @@ "target_label": "TY2026-27 ird taxable income total by band $161,001 - $162,000 (parked)" }, "filter": "taxable_income_band_row_171_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_172", @@ -46449,14 +48054,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46471,7 +48080,7 @@ "target_label": "TY2026-27 ird taxable income total by band $162,001 - $163,000 (parked)" }, "filter": "taxable_income_band_row_172_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_173", @@ -46501,14 +48110,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46523,7 +48136,7 @@ "target_label": "TY2026-27 ird taxable income total by band $163,001 - $164,000 (parked)" }, "filter": "taxable_income_band_row_173_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_174", @@ -46553,14 +48166,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46575,7 +48192,7 @@ "target_label": "TY2026-27 ird taxable income total by band $164,001 - $165,000 (parked)" }, "filter": "taxable_income_band_row_174_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_175", @@ -46605,14 +48222,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46627,7 +48248,7 @@ "target_label": "TY2026-27 ird taxable income total by band $165,001 - $166,000 (parked)" }, "filter": "taxable_income_band_row_175_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_176", @@ -46657,14 +48278,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46679,7 +48304,7 @@ "target_label": "TY2026-27 ird taxable income total by band $166,001 - $167,000 (parked)" }, "filter": "taxable_income_band_row_176_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_177", @@ -46709,14 +48334,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46731,7 +48360,7 @@ "target_label": "TY2026-27 ird taxable income total by band $167,001 - $168,000 (parked)" }, "filter": "taxable_income_band_row_177_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_178", @@ -46761,14 +48390,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46783,7 +48416,7 @@ "target_label": "TY2026-27 ird taxable income total by band $168,001 - $169,000 (parked)" }, "filter": "taxable_income_band_row_178_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_179", @@ -46813,14 +48446,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46835,7 +48472,7 @@ "target_label": "TY2026-27 ird taxable income total by band $169,001 - $170,000 (parked)" }, "filter": "taxable_income_band_row_179_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_180", @@ -46865,14 +48502,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46887,7 +48528,7 @@ "target_label": "TY2026-27 ird taxable income total by band $170,001 - $171,000 (parked)" }, "filter": "taxable_income_band_row_180_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_181", @@ -46917,14 +48558,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46939,7 +48584,7 @@ "target_label": "TY2026-27 ird taxable income total by band $171,001 - $172,000 (parked)" }, "filter": "taxable_income_band_row_181_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_182", @@ -46969,14 +48614,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -46991,7 +48640,7 @@ "target_label": "TY2026-27 ird taxable income total by band $172,001 - $173,000 (parked)" }, "filter": "taxable_income_band_row_182_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_183", @@ -47021,14 +48670,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47043,7 +48696,7 @@ "target_label": "TY2026-27 ird taxable income total by band $173,001 - $174,000 (parked)" }, "filter": "taxable_income_band_row_183_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_184", @@ -47073,14 +48726,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47095,7 +48752,7 @@ "target_label": "TY2026-27 ird taxable income total by band $174,001 - $175,000 (parked)" }, "filter": "taxable_income_band_row_184_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_185", @@ -47125,14 +48782,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47147,7 +48808,7 @@ "target_label": "TY2026-27 ird taxable income total by band $175,001 - $176,000 (parked)" }, "filter": "taxable_income_band_row_185_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_186", @@ -47177,14 +48838,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47199,7 +48864,7 @@ "target_label": "TY2026-27 ird taxable income total by band $176,001 - $177,000 (parked)" }, "filter": "taxable_income_band_row_186_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_187", @@ -47229,14 +48894,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47251,7 +48920,7 @@ "target_label": "TY2026-27 ird taxable income total by band $177,001 - $178,000 (parked)" }, "filter": "taxable_income_band_row_187_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_188", @@ -47281,14 +48950,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47303,7 +48976,7 @@ "target_label": "TY2026-27 ird taxable income total by band $178,001 - $179,000 (parked)" }, "filter": "taxable_income_band_row_188_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_189", @@ -47333,14 +49006,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47355,7 +49032,7 @@ "target_label": "TY2026-27 ird taxable income total by band $179,001 - $180,000 (parked)" }, "filter": "taxable_income_band_row_189_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_190", @@ -47385,14 +49062,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47407,7 +49088,7 @@ "target_label": "TY2026-27 ird taxable income total by band $180,001 - $181,000 (parked)" }, "filter": "taxable_income_band_row_190_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_191", @@ -47437,14 +49118,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47459,7 +49144,7 @@ "target_label": "TY2026-27 ird taxable income total by band $181,001 - $182,000 (parked)" }, "filter": "taxable_income_band_row_191_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_192", @@ -47489,14 +49174,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47511,7 +49200,7 @@ "target_label": "TY2026-27 ird taxable income total by band $182,001 - $183,000 (parked)" }, "filter": "taxable_income_band_row_192_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_193", @@ -47541,14 +49230,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47563,7 +49256,7 @@ "target_label": "TY2026-27 ird taxable income total by band $183,001 - $184,000 (parked)" }, "filter": "taxable_income_band_row_193_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_194", @@ -47593,14 +49286,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47615,7 +49312,7 @@ "target_label": "TY2026-27 ird taxable income total by band $184,001 - $185,000 (parked)" }, "filter": "taxable_income_band_row_194_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_195", @@ -47645,14 +49342,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47667,7 +49368,7 @@ "target_label": "TY2026-27 ird taxable income total by band $185,001 - $186,000 (parked)" }, "filter": "taxable_income_band_row_195_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_196", @@ -47697,14 +49398,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47719,7 +49424,7 @@ "target_label": "TY2026-27 ird taxable income total by band $186,001 - $187,000 (parked)" }, "filter": "taxable_income_band_row_196_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_197", @@ -47749,14 +49454,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47771,7 +49480,7 @@ "target_label": "TY2026-27 ird taxable income total by band $187,001 - $188,000 (parked)" }, "filter": "taxable_income_band_row_197_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_198", @@ -47801,14 +49510,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47823,7 +49536,7 @@ "target_label": "TY2026-27 ird taxable income total by band $188,001 - $189,000 (parked)" }, "filter": "taxable_income_band_row_198_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_199", @@ -47853,14 +49566,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47875,7 +49592,7 @@ "target_label": "TY2026-27 ird taxable income total by band $189,001 - $190,000 (parked)" }, "filter": "taxable_income_band_row_199_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_200", @@ -47905,14 +49622,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47927,7 +49648,7 @@ "target_label": "TY2026-27 ird taxable income total by band $190,001 - $191,000 (parked)" }, "filter": "taxable_income_band_row_200_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_201", @@ -47957,14 +49678,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -47979,7 +49704,7 @@ "target_label": "TY2026-27 ird taxable income total by band $191,001 - $192,000 (parked)" }, "filter": "taxable_income_band_row_201_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_202", @@ -48009,14 +49734,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48031,7 +49760,7 @@ "target_label": "TY2026-27 ird taxable income total by band $192,001 - $193,000 (parked)" }, "filter": "taxable_income_band_row_202_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_203", @@ -48061,14 +49790,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48083,7 +49816,7 @@ "target_label": "TY2026-27 ird taxable income total by band $193,001 - $194,000 (parked)" }, "filter": "taxable_income_band_row_203_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_204", @@ -48113,14 +49846,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48135,7 +49872,7 @@ "target_label": "TY2026-27 ird taxable income total by band $194,001 - $195,000 (parked)" }, "filter": "taxable_income_band_row_204_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_205", @@ -48165,14 +49902,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48187,7 +49928,7 @@ "target_label": "TY2026-27 ird taxable income total by band $195,001 - $196,000 (parked)" }, "filter": "taxable_income_band_row_205_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_206", @@ -48217,14 +49958,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48239,7 +49984,7 @@ "target_label": "TY2026-27 ird taxable income total by band $196,001 - $197,000 (parked)" }, "filter": "taxable_income_band_row_206_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_207", @@ -48269,14 +50014,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48291,7 +50040,7 @@ "target_label": "TY2026-27 ird taxable income total by band $197,001 - $198,000 (parked)" }, "filter": "taxable_income_band_row_207_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_208", @@ -48321,14 +50070,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48343,7 +50096,7 @@ "target_label": "TY2026-27 ird taxable income total by band $198,001 - $199,000 (parked)" }, "filter": "taxable_income_band_row_208_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_209", @@ -48373,14 +50126,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48395,7 +50152,7 @@ "target_label": "TY2026-27 ird taxable income total by band $199,001 - $200,000 (parked)" }, "filter": "taxable_income_band_row_209_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_210", @@ -48425,14 +50182,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48447,7 +50208,7 @@ "target_label": "TY2026-27 ird taxable income total by band $200,001 - $205,000 (parked)" }, "filter": "taxable_income_band_row_210_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_211", @@ -48477,14 +50238,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48499,7 +50264,7 @@ "target_label": "TY2026-27 ird taxable income total by band $205,001 - $210,000 (parked)" }, "filter": "taxable_income_band_row_211_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_212", @@ -48529,14 +50294,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48551,7 +50320,7 @@ "target_label": "TY2026-27 ird taxable income total by band $210,001 - $215,000 (parked)" }, "filter": "taxable_income_band_row_212_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_213", @@ -48581,14 +50350,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48603,7 +50376,7 @@ "target_label": "TY2026-27 ird taxable income total by band $215,001 - $220,000 (parked)" }, "filter": "taxable_income_band_row_213_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_214", @@ -48633,14 +50406,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48655,7 +50432,7 @@ "target_label": "TY2026-27 ird taxable income total by band $220,001 - $225,000 (parked)" }, "filter": "taxable_income_band_row_214_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_215", @@ -48685,14 +50462,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48707,7 +50488,7 @@ "target_label": "TY2026-27 ird taxable income total by band $225,001 - $230,000 (parked)" }, "filter": "taxable_income_band_row_215_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_216", @@ -48737,14 +50518,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48759,7 +50544,7 @@ "target_label": "TY2026-27 ird taxable income total by band $230,001 - $235,000 (parked)" }, "filter": "taxable_income_band_row_216_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_217", @@ -48789,14 +50574,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48811,7 +50600,7 @@ "target_label": "TY2026-27 ird taxable income total by band $235,001 - $240,000 (parked)" }, "filter": "taxable_income_band_row_217_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_218", @@ -48841,14 +50630,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48863,7 +50656,7 @@ "target_label": "TY2026-27 ird taxable income total by band $240,001 - $245,000 (parked)" }, "filter": "taxable_income_band_row_218_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_219", @@ -48893,14 +50686,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48915,7 +50712,7 @@ "target_label": "TY2026-27 ird taxable income total by band $245,001 - $250,000 (parked)" }, "filter": "taxable_income_band_row_219_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_220", @@ -48945,14 +50742,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -48967,7 +50768,7 @@ "target_label": "TY2026-27 ird taxable income total by band $250,001 - $255,000 (parked)" }, "filter": "taxable_income_band_row_220_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_221", @@ -48997,14 +50798,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49019,7 +50824,7 @@ "target_label": "TY2026-27 ird taxable income total by band $255,001 - $260,000 (parked)" }, "filter": "taxable_income_band_row_221_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_222", @@ -49049,14 +50854,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49071,7 +50880,7 @@ "target_label": "TY2026-27 ird taxable income total by band $260,001 - $265,000 (parked)" }, "filter": "taxable_income_band_row_222_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_223", @@ -49101,14 +50910,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49123,7 +50936,7 @@ "target_label": "TY2026-27 ird taxable income total by band $265,001 - $270,000 (parked)" }, "filter": "taxable_income_band_row_223_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_224", @@ -49153,14 +50966,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49175,7 +50992,7 @@ "target_label": "TY2026-27 ird taxable income total by band $270,001 - $275,000 (parked)" }, "filter": "taxable_income_band_row_224_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_225", @@ -49205,14 +51022,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49227,7 +51048,7 @@ "target_label": "TY2026-27 ird taxable income total by band $275,001 - $280,000 (parked)" }, "filter": "taxable_income_band_row_225_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_226", @@ -49257,14 +51078,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49279,7 +51104,7 @@ "target_label": "TY2026-27 ird taxable income total by band $280,001 - $285,000 (parked)" }, "filter": "taxable_income_band_row_226_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_227", @@ -49309,14 +51134,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49331,7 +51160,7 @@ "target_label": "TY2026-27 ird taxable income total by band $285,001 - $290,000 (parked)" }, "filter": "taxable_income_band_row_227_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_228", @@ -49361,14 +51190,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49383,7 +51216,7 @@ "target_label": "TY2026-27 ird taxable income total by band $290,001 - $295,000 (parked)" }, "filter": "taxable_income_band_row_228_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_229", @@ -49413,14 +51246,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49435,7 +51272,7 @@ "target_label": "TY2026-27 ird taxable income total by band $295,001 - $300,000 (parked)" }, "filter": "taxable_income_band_row_229_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_230", @@ -49465,14 +51302,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49487,7 +51328,7 @@ "target_label": "TY2026-27 ird taxable income total by band $300,000 - $350,000 (parked)" }, "filter": "taxable_income_band_row_230_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_231", @@ -49517,14 +51358,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49539,7 +51384,7 @@ "target_label": "TY2026-27 ird taxable income total by band $350,001 - $400,000 (parked)" }, "filter": "taxable_income_band_row_231_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_232", @@ -49569,14 +51414,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49591,7 +51440,7 @@ "target_label": "TY2026-27 ird taxable income total by band $400,001 - $450,000 (parked)" }, "filter": "taxable_income_band_row_232_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_233", @@ -49621,14 +51470,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49643,7 +51496,7 @@ "target_label": "TY2026-27 ird taxable income total by band $450,001 - $500,000 (parked)" }, "filter": "taxable_income_band_row_233_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_234", @@ -49673,14 +51526,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49695,7 +51552,7 @@ "target_label": "TY2026-27 ird taxable income total by band $500,001 - $550,000 (parked)" }, "filter": "taxable_income_band_row_234_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_235", @@ -49725,14 +51582,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49747,7 +51608,7 @@ "target_label": "TY2026-27 ird taxable income total by band $550,001 - $600,000 (parked)" }, "filter": "taxable_income_band_row_235_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_236", @@ -49777,14 +51638,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49799,7 +51664,7 @@ "target_label": "TY2026-27 ird taxable income total by band $600,001 - $650,000 (parked)" }, "filter": "taxable_income_band_row_236_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_237", @@ -49829,14 +51694,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49851,7 +51720,7 @@ "target_label": "TY2026-27 ird taxable income total by band $650,001 - $700,000 (parked)" }, "filter": "taxable_income_band_row_237_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_238", @@ -49881,14 +51750,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49903,7 +51776,7 @@ "target_label": "TY2026-27 ird taxable income total by band $700,001 - $750,000 (parked)" }, "filter": "taxable_income_band_row_238_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_239", @@ -49933,14 +51806,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -49955,7 +51832,7 @@ "target_label": "TY2026-27 ird taxable income total by band $750,001 - $800,000 (parked)" }, "filter": "taxable_income_band_row_239_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_240", @@ -49985,14 +51862,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -50007,7 +51888,7 @@ "target_label": "TY2026-27 ird taxable income total by band $800,001 - $850,000 (parked)" }, "filter": "taxable_income_band_row_240_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_241", @@ -50037,14 +51918,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -50059,7 +51944,7 @@ "target_label": "TY2026-27 ird taxable income total by band $850,001 - $900,000 (parked)" }, "filter": "taxable_income_band_row_241_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_242", @@ -50089,14 +51974,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -50111,7 +52000,7 @@ "target_label": "TY2026-27 ird taxable income total by band $900,001 - $950,000 (parked)" }, "filter": "taxable_income_band_row_242_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_243", @@ -50141,14 +52030,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -50163,7 +52056,7 @@ "target_label": "TY2026-27 ird taxable income total by band $950,001 - $1,000,000 (parked)" }, "filter": "taxable_income_band_row_243_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "ird_taxable_income_total_by_band__row_244", @@ -50193,14 +52086,18 @@ "assertion_policy": "observed_only", "metadata": { "contract_target_id": "ird_taxable_income_total_by_band", - "activation_status": "requires_g8r2_taxable_income_contract_intervals_and_ageing", + "activation_status": "requires_prerequisites", "criticality": "release_blocking", "measure_kind": "prepared_column", "publisher": "Inland Revenue", "target_role": "calibration", "reference_set": "calibration", "method_card_row": "MC5", - "parking_reason": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "parking_reason": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement.", + "reference_prerequisites": "[\"reference_profile:aging_index\",\"measurement:ird_taxable_income_ty2027_v1\"]", + "required_reference_profile": "aging_index", + "required_measurement_binding": "ird_taxable_income_ty2027_v1", + "reference_value_kind": "money" }, "hierarchy": { "provider": { @@ -50215,7 +52112,7 @@ "target_label": "TY2026-27 ird taxable income total by band Over $1,000,000 (parked)" }, "filter": "taxable_income_band_row_244_indicator", - "notes": "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." + "notes": "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." }, { "name": "msd_jobseeker_support_recipients__age_18_24", diff --git a/packages/microcosm-build/src/microcosm/build/reference_factors.py b/packages/microcosm-build/src/microcosm/build/reference_factors.py new file mode 100644 index 0000000000..1a02dade36 --- /dev/null +++ b/packages/microcosm-build/src/microcosm/build/reference_factors.py @@ -0,0 +1,752 @@ +"""Closed, declaration-driven factor calculations with exact feed operands. + +The operational rational is rounded once. Irrational roots remain certified +intervals in the evidence; they are never represented as exact rationals. +Composition checks declared evidence; compilation must replay it against the +facts returned by the authenticated artifact loader. +""" + +from __future__ import annotations + +import hashlib +from collections.abc import Iterable, Mapping +from datetime import date, timedelta +from decimal import Decimal, InvalidOperation +from fractions import Fraction + +from microcosm.build.ledger_artifact import LexicalFloat, chronicle_feed_identity +from microcosm.build.ledger_targets import ( + ALLOWED_ASSERTION_POLICIES, + fact_matches_selector, + selector_field_is_supported, +) +from microcosm.graph.canonical import canonical_json + +OPERATION = "projected_period_average_ratio" +OPERATION_VERSION = 1 +# Exact powers in projected receipts grow with both schedule size and root +# precision. Keep ordinary schedules within the stock integer serialization +# budget, including when rounding needs a finer root enclosure. +_MAX_SUBPERIODS_PER_YEAR = 12 +_MAX_ROUNDING_DIGITS = 18 +_MAX_RECEIPT_ROOT_PLACES = 256 +_DECLARATION_FIELDS = frozenset( + { + "schema_version", + "id", + "operation", + "operation_version", + "purpose", + "feed_identity", + "source_period", + "target_period", + "source_schedule", + "target_schedule", + "growth", + "subperiods_per_year", + "projection_policy", + "rounding", + "expected_operational_factor", + "validity", + "evidence", + "decision_references", + } +) +_VALIDATION_FIELDS = frozenset( + { + "unit", + "source_sha256", + "source_vintage", + "entity_role", + "provenance_class", + "assertion", + "period_coverage", + "source_column_id", + } +) + + +def factor_document_sha256(document: object) -> str: + """Hash canonical declaration/evidence bytes without a registry identity.""" + return hashlib.sha256(canonical_json(document)).hexdigest() + + +def _mapping(value: object, label: str) -> dict: + if not isinstance(value, Mapping): + raise ValueError(f"{label} must be an object.") + return dict(value) + + +def _closed(value: object, fields: set | frozenset, label: str) -> dict: + result = _mapping(value, label) + unknown = result.keys() - fields + if unknown: + raise ValueError(f"Unknown {label} fields: {sorted(unknown)}.") + return result + + +def _closed_feed_identity(value: object, label: str) -> dict: + identity = _mapping(value, label) + normalized = chronicle_feed_identity(identity) + unknown = identity.keys() - normalized.keys() + if unknown: + raise ValueError(f"Unknown {label} fields: {sorted(unknown)}.") + return normalized + + +def _list(value: object, label: str) -> list: + if not isinstance(value, (list, tuple)) or not value: + raise ValueError(f"{label} must be a nonempty list.") + return list(value) + + +def _decimal(value: object, label: str) -> Fraction: + if isinstance(value, bool) or not isinstance(value, (str, int, Decimal)): + raise ValueError(f"{label} requires a finite lexical decimal, never a float.") + try: + result = Decimal(value) + except (InvalidOperation, ValueError) as exc: + raise ValueError(f"{label} requires a finite decimal.") from exc + if not result.is_finite(): + raise ValueError(f"{label} requires a finite decimal.") + return Fraction(result) + + +def _rational(value: Fraction) -> dict: + return {"numerator": value.numerator, "denominator": value.denominator} + + +def _read_rational(value: object, label: str) -> Fraction: + row = _closed(value, {"numerator", "denominator"}, label) + numerator, denominator = row.get("numerator"), row.get("denominator") + if type(numerator) is not int or type(denominator) is not int or denominator <= 0: + raise ValueError( + f"{label} requires integer numerator and positive denominator." + ) + return Fraction(numerator, denominator) + + +def _integer_root(value: int, degree: int) -> int: + lower, upper = 0, 1 << ((value.bit_length() + degree - 1) // degree) + while lower < upper: + middle = (lower + upper + 1) // 2 + if middle**degree <= value: + lower = middle + else: + upper = middle - 1 + return lower + + +def certified_nth_root_bounds( + value: Fraction, degree: int, decimal_places: int +) -> tuple[Fraction, Fraction, bool]: + """Enclose a positive root on an integer grid; mark only exact roots exact.""" + if value <= 0 or type(degree) is not int or degree <= 0: + raise ValueError("Root radicand and degree must be positive.") + if type(decimal_places) is not int or not 0 <= decimal_places <= 4096: + raise ValueError("Root precision must be between 0 and 4096.") + numerator_root = _integer_root(value.numerator, degree) + denominator_root = _integer_root(value.denominator, degree) + if ( + numerator_root**degree == value.numerator + and denominator_root**degree == value.denominator + ): + exact = Fraction(numerator_root, denominator_root) + return exact, exact, True + scale = 10**decimal_places + floor = _integer_root(value.numerator * scale**degree // value.denominator, degree) + return Fraction(floor, scale), Fraction(floor + 1, scale), False + + +def _round_nearest(value: Fraction, digits: int) -> int: + scaled = value * 10**digits + quotient, remainder = divmod(scaled.numerator, scaled.denominator) + twice = 2 * remainder + return quotient + ( + twice > scaled.denominator + or (twice == scaled.denominator and quotient % 2 == 1) + ) + + +def _declaration(declaration: object) -> dict: + row = _closed(declaration, _DECLARATION_FIELDS, "factor declaration") + missing = _DECLARATION_FIELDS - row.keys() + if missing: + raise ValueError(f"Factor declaration missing fields: {sorted(missing)}.") + if type(row["schema_version"]) is not int or row["schema_version"] != 1: + raise ValueError("Factor declaration requires schema_version 1.") + if ( + row["operation"] != OPERATION + or type(row["operation_version"]) is not int + or row["operation_version"] != OPERATION_VERSION + ): + raise ValueError("Unknown factor operation or operation version.") + if not isinstance(row["id"], str) or not row["id"]: + raise ValueError("Factor id must be nonempty text.") + if row["purpose"] not in {"profile_input", "diagnostic"}: + raise ValueError("Unknown factor purpose.") + for field in ("source_period", "target_period"): + label = row[field] + if type(label) not in {str, int} or isinstance(label, str) and not label: + raise ValueError("Factor period labels require nonempty text or integers.") + if row["projection_policy"] != "observed_preferred_latest_contiguous": + raise ValueError("Unknown factor projection policy.") + frequency = row["subperiods_per_year"] + if type(frequency) is not int or not 1 <= frequency <= _MAX_SUBPERIODS_PER_YEAR: + raise ValueError( + "subperiods_per_year must be an integer from 1 to " + f"{_MAX_SUBPERIODS_PER_YEAR} for serializable exact receipts." + ) + rounding = _closed(row["rounding"], {"digits", "mode"}, "factor rounding") + if ( + type(rounding.get("digits")) is not int + or not 0 <= rounding["digits"] <= _MAX_ROUNDING_DIGITS + ): + raise ValueError( + "Factor rounding digits must be an integer from 0 to " + f"{_MAX_ROUNDING_DIGITS} for serializable exact receipts." + ) + if rounding.get("mode") != "nearest_half_even": + raise ValueError("Factor rounding must be nearest_half_even.") + expected = _read_rational(row["expected_operational_factor"], "expected factor") + if ( + expected <= 0 + or row["expected_operational_factor"]["denominator"] != 10 ** rounding["digits"] + ): + raise ValueError("Expected operational factor must be positive p / 10**digits.") + validity = _closed( + row["validity"], + {"declared_on", "valid_from", "valid_until", "as_of"}, + "factor validity", + ) + try: + dates = { + key: date.fromisoformat(validity[key]) + for key in ("declared_on", "valid_from", "valid_until", "as_of") + } + except (KeyError, TypeError, ValueError) as exc: + raise ValueError("Factor validity requires explicit ISO dates.") from exc + if ( + not dates["declared_on"] <= dates["as_of"] + or not dates["valid_from"] <= dates["as_of"] <= dates["valid_until"] + ): + raise ValueError( + "Factor declaration is expired or not yet valid at its declared as_of." + ) + for key in ("evidence", "decision_references"): + if any(not isinstance(item, str) or not item for item in _list(row[key], key)): + raise ValueError(f"{key} must contain nonempty text.") + row["feed_identity"] = _closed_feed_identity( + row["feed_identity"], "factor declaration feed identity" + ) + return row + + +def _schedule(value: object, frequency: int, *, target: bool) -> list[dict]: + rows = _list(value, "factor schedule") + if len(rows) != frequency: + raise ValueError("Factor schedule must contain every declared subperiod once.") + result, previous_end, periods = [], None, set() + for index, raw in enumerate(rows): + fields = {"selector", "validation", "weight", "sequence"} + if target: + fields.add("projection_offset") + row = _closed(raw, fields, "factor schedule slot") + if type(row.get("sequence")) is not int or row["sequence"] != index: + raise ValueError("Factor schedule is misordered or noncontiguous.") + if target and ( + type(row.get("projection_offset")) is not int + or row["projection_offset"] != index + ): + raise ValueError("Invalid projection offsets.") + selector = _mapping(row.get("selector"), "factor selector") + if not selector or any( + not selector_field_is_supported(key) for key in selector + ): + raise ValueError( + "Unknown or empty factor selector; use the closed selector vocabulary." + ) + if "period_value" not in selector or isinstance( + selector["period_value"], (list, tuple) + ): + raise ValueError("Each schedule slot must select one explicit period.") + period = str(selector["period_value"]) + if period in periods: + raise ValueError("Duplicate factor schedule period.") + periods.add(period) + validation = _validation(row.get("validation")) + coverage = validation["period_coverage"] + try: + start, end = ( + date.fromisoformat(coverage["start_date"]), + date.fromisoformat(coverage["end_date"]), + ) + except (KeyError, TypeError, ValueError) as exc: + raise ValueError("Factor schedules require ISO period coverage.") from exc + if start > end or ( + previous_end is not None and start != previous_end + timedelta(days=1) + ): + raise ValueError("Factor schedule coverage is misordered or noncontiguous.") + previous_end = end + if _decimal(row.get("weight"), "schedule weight") <= 0: + raise ValueError("Averaging weights must be positive.") + result.append(row) + return result + + +def _validation(value: object) -> dict: + result = _closed(value, _VALIDATION_FIELDS, "factor operand validation") + required = _VALIDATION_FIELDS - {"source_column_id"} + if required - result.keys(): + raise ValueError( + "Factor operands require unit, source hash/vintage, role, assertion, provenance and coverage." + ) + if result["assertion"] not in {"observation", "source_projection"}: + raise ValueError("Unknown factor assertion.") + coverage = _closed( + result["period_coverage"], + {"start_date", "end_date", "basis", "source_period_label", "notes"}, + "factor operand coverage", + ) + if not {"start_date", "end_date"} <= coverage.keys(): + raise ValueError("Factor operand coverage requires both endpoints.") + for key in required - {"period_coverage"}: + if not isinstance(result[key], str) or not result[key]: + raise ValueError("Factor operand validations require nonempty text.") + source_hash = result["source_sha256"] + if len(source_hash) != 64 or any( + character not in "0123456789abcdef" for character in source_hash + ): + raise ValueError("Factor operand source hash must be a lowercase SHA-256.") + return result + + +def _operand( + slot: dict, + facts: tuple, + *, + optional: bool = False, + assertion_policy: str = "observed_only", +) -> tuple[Fraction, dict] | None: + selector = slot["selector"] + # Exact keys do not make duplicate same-period source vintages unambiguous. + broad = { + key: value + for key, value in selector.items() + if key + not in { + "aggregate_fact_key", + "semantic_fact_key", + "legacy_fact_key", + "source_record_id", + "record_set_id", + "layout_record_set_id", + "record_set_spec_id", + "layout_record_set_spec_id", + } + } + if ( + "period_value" in broad + and sum(fact_matches_selector(fact, broad) for fact in facts) > 1 + ): + raise ValueError("Duplicate factor period across source vintages or facts.") + matches = [fact for fact in facts if fact_matches_selector(fact, selector)] + if not matches and optional: + return None + if len(matches) != 1: + raise ValueError( + f"Factor selector must resolve exactly once; found {len(matches)}." + ) + fact = matches[0] + validation = _validation(slot["validation"]) + actual = { + "unit": fact.get("observed_measure", {}).get("unit"), + "source_sha256": fact.get("source", {}).get("source_sha256"), + "source_vintage": fact.get("source", {}).get("vintage"), + "entity_role": fact.get("entity", {}).get("role"), + "provenance_class": fact.get("provenance_class"), + "assertion": fact.get("assertion", "observation"), + "period_coverage": fact.get("period_coverage", {}), + "source_column_id": fact.get("layout", {}).get("source_column_id"), + } + for key, expected in validation.items(): + if key == "period_coverage": + if any(actual[key].get(field) != item for field, item in expected.items()): + raise ValueError("Factor operand period coverage mismatch.") + elif actual[key] != expected: + raise ValueError(f"Factor operand {key} mismatch.") + # Reuse the existing target assertion-policy vocabulary after all match paths. + if ( + actual["assertion"] == "source_projection" + and assertion_policy != "allow_source_projection" + ): + raise ValueError("Source projections require allow_source_projection.") + value = fact.get("value") + if isinstance(value, bool): + raise ValueError("Boolean factor operand is not numeric.") + if isinstance(value, LexicalFloat): + token = value.lexical_token + recovered = str(float(value)) + if _decimal(token, "feed numeric token") != _decimal( + recovered, "float decimal recovery" + ): + raise ValueError( + "Float conversion does not reproduce the feed lexical numeric token." + ) + proof = { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": token, + "recovered_decimal": recovered, + "decimal_values_equal": True, + } + elif type(value) is int: + token = str(value) + proof = { + "numeric_representation": "exact_integer", + "lexical_token": token, + "recovered_decimal": token, + "decimal_values_equal": True, + } + elif isinstance(value, Decimal): + token = str(value) + proof = { + "numeric_representation": "exact_decimal", + "lexical_token": token, + "recovered_decimal": token, + "decimal_values_equal": True, + } + else: + raise ValueError( + "Factor operand lacks an authenticated lexical numeric token; " + "load the artifact with lexical_floats=True." + ) + numeric = _decimal(token, "feed numeric token") + return numeric, { + "selector": selector, + "aggregate_fact_key": fact.get("aggregate_fact_key"), + "decimal_operand": token, + "numeric_token_proof": proof, + "validation": validation, + "period": fact.get("period"), + "source": fact.get("source"), + "unit": actual["unit"], + "assertion": actual["assertion"], + "provenance_class": actual["provenance_class"], + "entity_role": actual["entity_role"], + "period_coverage": actual["period_coverage"], + } + + +def resolve_reference_factor( + declaration: Mapping, facts: Iterable, feed_identity: Mapping +) -> tuple[dict, dict]: + """Resolve one closed operation, returning its operational rational and proof.""" + row = _declaration(declaration) + feed_identity = chronicle_feed_identity( + _mapping(feed_identity, "factor feed identity") + ) + if canonical_json(row["feed_identity"]) != canonical_json(feed_identity): + raise ValueError("Factor feed identity mismatch; re-declaration is required.") + fact_rows = tuple(facts) + frequency = row["subperiods_per_year"] + source = _schedule(row["source_schedule"], frequency, target=False) + target = _schedule(row["target_schedule"], frequency, target=True) + source_values, source_evidence = [], [] + for slot in source: + if slot["validation"]["assertion"] != "observation": + raise ValueError("Source schedule requires observations.") + value, evidence = _operand(slot, fact_rows) + if value <= 0: + raise ValueError("Factor denominator operands must be positive.") + source_values.append((value, _decimal(slot["weight"], "source weight"))) + evidence.update({"weight": slot["weight"], "sequence": slot["sequence"]}) + source_evidence.append(evidence) + denominator = sum(value * weight for value, weight in source_values) / sum( + weight for _, weight in source_values + ) + growth = row["growth"] + growth_evidence, effective_growth = None, Fraction(0) + if growth is not None: + growth = _closed( + growth, + { + "selector", + "validation", + "unit_multiplier", + "scenario_delta", + "sensitivity_provenance", + "assertion_policy", + }, + "factor growth", + ) + _validation(growth.get("validation")) + selector = _mapping(growth.get("selector"), "growth selector") + if not selector or any( + not selector_field_is_supported(key) for key in selector + ): + raise ValueError("Unknown growth selector field.") + policy = growth.get("assertion_policy") + if policy not in ALLOWED_ASSERTION_POLICIES: + raise ValueError("Unknown growth assertion policy.") + growth_value, growth_evidence = _operand( + growth, fact_rows, assertion_policy=policy + ) + multiplier = _decimal(growth.get("unit_multiplier"), "growth unit multiplier") + delta = _decimal(growth.get("scenario_delta"), "scenario delta") + if multiplier <= 0: + raise ValueError("Growth unit multiplier must be positive.") + if any( + not isinstance(item, str) or not item + for item in _list( + growth.get("sensitivity_provenance"), "sensitivity provenance" + ) + ): + raise ValueError("Missing sensitivity provenance.") + effective_growth = (growth_value + delta) * multiplier + growth_evidence.update( + { + "unit_multiplier": growth["unit_multiplier"], + "scenario_delta": growth["scenario_delta"], + "sensitivity_provenance": growth["sensitivity_provenance"], + "effective_growth": _rational(effective_growth), + } + ) + if 1 + effective_growth <= 0: + raise ValueError("Effective annual growth must have positive 1 + g.") + observations, target_evidence, gap = [], [], False + for slot in target: + if slot["validation"]["assertion"] != "observation": + raise ValueError("Target schedules prefer observations only.") + resolved = _operand(slot, fact_rows, optional=slot["sequence"] != 0) + if resolved is None: + gap = True + observations.append(None) + target_evidence.append( + { + "selector": slot["selector"], + "validation": slot["validation"], + "status": "projected", + } + ) + else: + if gap: + raise ValueError( + "Observed target subperiods must be contiguous from the anchor." + ) + value, evidence = resolved + if value <= 0: + raise ValueError("Observed target anchors must be positive.") + observations.append(value) + target_evidence.append({**evidence, "status": "observed"}) + if gap and growth is None: + raise ValueError("Projected target periods require a declared growth operand.") + last_observed = max( + index for index, value in enumerate(observations) if value is not None + ) + anchor = observations[last_observed] + target_weights = [_decimal(slot["weight"], "target weight") for slot in target] + + def numerator_at(root: Fraction) -> Fraction: + return sum( + (value if value is not None else anchor * root ** (index - last_observed)) + * target_weights[index] + for index, value in enumerate(observations) + ) / sum(target_weights) + + digits = row["rounding"]["digits"] + precision = digits + 8 + while precision <= _MAX_RECEIPT_ROOT_PLACES: + lower, upper, exact = certified_nth_root_bounds( + 1 + effective_growth, frequency, precision + ) + numerator_lower, numerator_upper = numerator_at(lower), numerator_at(upper) + factor_lower, factor_upper = ( + numerator_lower / denominator, + numerator_upper / denominator, + ) + rounded_lower, rounded_upper = ( + _round_nearest(factor_lower, digits), + _round_nearest(factor_upper, digits), + ) + if rounded_lower == rounded_upper: + break + precision *= 2 + else: + raise ValueError( + "Factor rounding cannot be certified within the supported exact receipt " + "precision." + ) + factor = {"numerator": rounded_lower, "denominator": 10**digits} + if rounded_lower <= 0: + raise ValueError("Operational factor must be positive.") + if factor != row["expected_operational_factor"]: + raise ValueError( + f"Declared expected factor mismatch: computed {factor}; re-declaration is required." + ) + for index, evidence in enumerate(target_evidence): + evidence.update( + { + "sequence": index, + "weight": target[index]["weight"], + "projection_offset": 0 + if observations[index] is not None + else index - last_observed, + } + ) + if observations[index] is None: + evidence["projection_anchor"] = { + "aggregate_fact_key": target_evidence[last_observed][ + "aggregate_fact_key" + ] + } + receipt = { + "schema_version": 1, + "operation": OPERATION, + "operation_version": OPERATION_VERSION, + "factor_id": row["id"], + "declaration_sha256": factor_document_sha256(row), + "feed_identity": dict(feed_identity), + "source_period": row["source_period"], + "target_period": row["target_period"], + "source_schedule": source_evidence, + "target_schedule": target_evidence, + "subperiods_per_year": frequency, + "projection_policy": row["projection_policy"], + "denominator_mean": _rational(denominator), + "growth": growth_evidence, + "root_bounds": { + "lower": _rational(lower), + "upper": _rational(upper), + "exact": exact, + "decimal_places": precision, + "degree": frequency, + "radicand": _rational(1 + effective_growth), + }, + "numerator_mean_bounds": { + "lower": _rational(numerator_lower), + "upper": _rational(numerator_upper), + }, + "unrounded_factor_bounds": { + "lower": _rational(factor_lower), + "upper": _rational(factor_upper), + }, + "rounding": row["rounding"], + "operational_factor": factor, + "validity": row["validity"], + "evidence": row["evidence"], + "decision_references": row["decision_references"], + } + receipt["receipt_sha256"] = factor_document_sha256(receipt) + return factor, receipt + + +def validate_factor_context( + context: Mapping, selected_ids: Iterable[str] | None = None +) -> dict[str, dict]: + """Check selected declared evidence without claiming source authentication. + + Only selected declarations/evidence are validated or returned. Independent + profile edits therefore cannot change a branch's identity or availability. + """ + document = _closed( + context, + {"schema_version", "factors", "country", "feed_identity"}, + "factor context", + ) + if ( + type(document.get("schema_version")) is not int + or document["schema_version"] != 1 + ): + raise ValueError("Factor context requires schema_version 1.") + if "feed_identity" in document: + document["feed_identity"] = _closed_feed_identity( + document["feed_identity"], "factor context feed identity" + ) + entries = _list(document.get("factors"), "factor context entries") + by_id = {} + for raw in entries: + entry = _mapping(raw, "factor context entry") + declaration = _mapping(entry.get("declaration"), "factor declaration") + factor_id = declaration.get("id") + if not isinstance(factor_id, str) or not factor_id or factor_id in by_id: + raise ValueError("Factor ids must be unique nonempty text.") + by_id[factor_id] = entry + selected = list(by_id) if selected_ids is None else list(selected_ids) + result = {} + for factor_id in selected: + if factor_id not in by_id: + raise ValueError(f"Missing selected factor {factor_id!r}.") + entry = _closed( + by_id[factor_id], + {"declaration", "operational_factor", "receipt"}, + "factor context entry", + ) + declaration = _declaration(entry["declaration"]) + if ( + "feed_identity" in document + and document["feed_identity"] != declaration["feed_identity"] + ): + raise ValueError( + "Factor context feed identity is incompatible with the declaration." + ) + factor = entry.get("operational_factor") + _read_rational(factor, "declared operational factor") + if factor != declaration["expected_operational_factor"]: + raise ValueError( + "Declared operational factor differs from its expectation." + ) + receipt = _mapping(entry.get("receipt"), "factor receipt") + body = {key: value for key, value in receipt.items() if key != "receipt_sha256"} + if receipt.get("receipt_sha256") != factor_document_sha256(body): + raise ValueError("Factor receipt hash mismatch.") + if ( + type(receipt.get("schema_version")) is not int + or receipt.get("schema_version") != 1 + or receipt.get("operation") != declaration["operation"] + or type(receipt.get("operation_version")) is not int + or receipt.get("operation_version") != declaration["operation_version"] + or receipt.get("factor_id") != factor_id + or receipt.get("declaration_sha256") != factor_document_sha256(declaration) + or receipt.get("operational_factor") != factor + or receipt.get("feed_identity") != declaration["feed_identity"] + ): + raise ValueError("Factor declaration and receipt are incompatible.") + result[factor_id] = entry + return result + + +def require_current_factors(selected: Mapping[str, dict], *, today: date) -> None: + """Require current declarations from ``validate_factor_context``'s result. + + The currency check guards new runs only. Validation and replay remain pure + functions of their recorded inputs; run entry supplies the explicit date. + """ + outside_validity = [] + for factor_id, entry in selected.items(): + validity = entry["declaration"]["validity"] + if not ( + date.fromisoformat(validity["valid_from"]) + <= today + <= date.fromisoformat(validity["valid_until"]) + ): + outside_validity.append(factor_id) + if outside_validity: + raise ValueError( + f"Selected factors {sorted(outside_validity)} are expired or not yet " + f"valid on {today.isoformat()}; a reviewed re-declaration is needed." + ) + + +def replay_reference_factor( + declaration: Mapping, + facts: Iterable, + feed_identity: Mapping, + operational_factor: Mapping, + receipt: Mapping, +) -> None: + """Authenticate evidence by recomputing it from the loaded feed facts.""" + factor, recomputed = resolve_reference_factor(declaration, facts, feed_identity) + if factor != operational_factor or canonical_json(recomputed) != canonical_json( + receipt + ): + raise ValueError("Factor replay differs from declared result or evidence.") diff --git a/packages/microcosm-build/src/microcosm/build/reference_intervals.py b/packages/microcosm-build/src/microcosm/build/reference_intervals.py new file mode 100644 index 0000000000..250be3fd64 --- /dev/null +++ b/packages/microcosm-build/src/microcosm/build/reference_intervals.py @@ -0,0 +1,976 @@ +"""Exact income-band intervals with declared semantics and rational cuts. + +Country data declares every interval table: its entity, currency, input unit, +income and universe columns, closure, nil band, negative-income policy, first +lower cut, source locator and diagnostics window. This module supplies no +default for any of them. It validates the declarations, scales cuts exactly, +classifies signed integer-cent amounts and reports fixed-weight boundary +diagnostics. + +Each cut is stored once: a positive band's lower cut is its predecessor's +upper cut, and the first positive band starts at the declared first lower cut. +Source cuts are integer cents. Scaling by a positive rational factor produces +reduced rational cents through integer cross-products and never rounds a +scaled cut. A scaled table keeps its source cuts and the digest of its source +table, and cannot be scaled again. + +Classification validates every record before computing any band. A universe +status is ``included``, ``excluded`` or ``unresolved``; an unresolved record, +an invalid status or an invalid amount on an included record refuses with a +summary of counts by reason. Excluded records never enter a band. Amounts are +signed integers; booleans, floats, strings, missing and nonfinite values are +invalid, and nothing converts a float to cents. + +Diagnostics weigh records with ``frame.resolve_weights(entity)``. They report +weighted mass near every finite cut and each positive band's weighted count +and amount under the declared closure and the other closure, computed +exactly. They never change a reference value or target. A published histogram +does not identify the publisher's mass exactly on a cut, so publisher +reclassification is unavailable: the report gives only the fixed-population +model measurement change. Records below the first cut remain visible, and +floored negative records retain their signed pre-floor amounts and their +destination under each closure. +""" + +from __future__ import annotations + +import copy +import hashlib +import json +import math +from collections import Counter +from collections.abc import Mapping, Sequence +from dataclasses import dataclass +from fractions import Fraction +from numbers import Integral + +import numpy as np + +from microcosm.graph.canonical import canonical_json + +__all__ = [ + "BELOW_FIRST_CUT", + "EXCLUDED", + "INTERVAL_DOCUMENT_SCHEMA_VERSION", + "IntervalPreparationError", + "IntervalTable", + "alternative_closure", + "boundary_diagnostics", + "classify_records", + "frame_boundary_diagnostics", + "interval_document_sha256", + "interval_indicators", + "interval_input_fingerprint", + "interval_table", + "scale_interval_document", + "scale_interval_table", + "source_interval_table", + "validate_interval_document", +] + +INTERVAL_DOCUMENT_SCHEMA_VERSION = 1 +SCALING_OPERATION = "exact_cut_multiplication" +BELOW_FIRST_CUT = -1 +EXCLUDED = -2 +CLOSURES = ("left", "right") +NIL_BAND_STATES = ("present", "absent") +NEGATIVE_INCOME_POLICIES = ("floor_zero", "refuse") +INPUT_UNITS = ("integer_cent",) +UNIVERSE_STATES = ("included", "excluded", "unresolved") +PUBLISHER_RECLASSIFICATION = "unavailable" +LIMITATION = ( + "A published histogram does not identify the publisher's mass exactly on a " + "cut, so the publisher's reclassification under the alternative closure " + "cannot be recovered. These are fixed-weight model measurement changes; " + "reference values and calibration targets are unchanged." +) + +_DOCUMENT_FIELDS = frozenset( + {"schema_version", "country", "description", "disclosure", "tables"} +) +_TABLE_FIELDS = frozenset( + { + "id", + "entity", + "currency", + "input_unit", + "income_column", + "universe_column", + "source_period", + "target_period", + "positive_band_closure", + "nil_band", + "negative_income_policy", + "first_lower_cut_cents", + "source_locator", + "diagnostics", + "bands", + } +) +_SCALED_TABLE_FIELDS = frozenset({"scaling", "source_first_lower_cut_cents"}) +_OPTIONAL_TABLE_FIELDS = frozenset({"description"}) +_BAND_FIELDS = frozenset({"id", "kind", "indicator"}) +_OPTIONAL_BAND_FIELDS = frozenset( + {"count_reference", "amount_reference", "source_label"} +) +_SCALING_FIELDS = frozenset( + { + "operation", + "factor_id", + "operational_factor", + "factor_declaration_sha256", + "factor_receipt_sha256", + "source_table_sha256", + "source_cuts_sha256", + } +) +_DIAGNOSTIC_FIELDS = frozenset( + {"boundary_window_cents", "alternative_positive_band_closure"} +) + + +class IntervalPreparationError(ValueError): + """Records cannot be classified; ``summary`` counts every reason.""" + + def __init__(self, summary: Mapping[str, object]) -> None: + self.summary = dict(summary) + super().__init__( + "Interval preparation refused before emitting indicators: " + + json.dumps(self.summary, sort_keys=True) + ) + + +@dataclass(frozen=True) +class IntervalTable: + """One validated table. ``cuts`` holds the first lower cut then each finite upper cut.""" + + id: str + entity: str + income_column: str + universe_column: str + closure: str + nil_present: bool + negative_income_policy: str + window_cents: int + band_ids: tuple[str, ...] + indicators: tuple[str, ...] + nil_index: int | None + positive_indices: tuple[int, ...] + cuts: tuple[Fraction, ...] + scaled: bool + declaration: Mapping[str, object] + + +def interval_document_sha256(document: object) -> str: + """Hash canonical document bytes.""" + + return hashlib.sha256(canonical_json(document)).hexdigest() + + +def alternative_closure(closure: str) -> str: + """The other positive-band closure, whichever is declared.""" + + if closure not in CLOSURES: + raise ValueError("Positive band closure must be 'left' or 'right'.") + return "left" if closure == "right" else "right" + + +def _mapping(value: object, label: str) -> dict: + if not isinstance(value, Mapping): + raise ValueError(f"{label} must be an object.") + return dict(value) + + +def _closed(value: object, required: frozenset, optional: frozenset, label: str): + row = _mapping(value, label) + unknown = row.keys() - required - optional + missing = required - row.keys() + if unknown: + raise ValueError(f"Unknown {label} fields: {sorted(unknown)}.") + if missing: + raise ValueError(f"{label} is missing declared fields: {sorted(missing)}.") + return row + + +def _text(value: object, label: str) -> str: + if not isinstance(value, str) or not value: + raise ValueError(f"{label} must be nonempty text.") + return value + + +def _choice(value: object, choices: tuple[str, ...], label: str) -> str: + if not isinstance(value, str) or value not in choices: + raise ValueError(f"{label} must be declared as one of {list(choices)}.") + return value + + +def _period(value: object, label: str): + if isinstance(value, bool) or type(value) not in {int, str}: + raise ValueError(f"{label} must be an integer or nonempty text.") + if isinstance(value, str) and not value: + raise ValueError(f"{label} must be an integer or nonempty text.") + return value + + +def _integer_cents(value: object, label: str) -> int: + # ``type`` rather than ``isinstance`` keeps booleans out; JSON floats, + # infinity and NaN are floats and refuse here too. + if type(value) is not int: + raise ValueError(f"{label} must be integer cents, never a float or boolean.") + return value + + +def _rational_cents(value: object, label: str) -> Fraction: + row = _closed(value, frozenset({"numerator", "denominator"}), frozenset(), label) + numerator, denominator = row["numerator"], row["denominator"] + if type(numerator) is not int or type(denominator) is not int or denominator <= 0: + raise ValueError( + f"{label} requires integer numerator and positive integer denominator." + ) + if math.gcd(numerator, denominator) != 1: + raise ValueError(f"{label} must be a reduced rational.") + return Fraction(numerator, denominator) + + +def _rational(value: Fraction) -> dict[str, int]: + return {"numerator": value.numerator, "denominator": value.denominator} + + +def _positive_factor(value: object) -> Fraction: + row = _closed( + value, frozenset({"numerator", "denominator"}), frozenset(), "scaling factor" + ) + numerator, denominator = row["numerator"], row["denominator"] + if ( + type(numerator) is not int + or type(denominator) is not int + or numerator <= 0 + or denominator <= 0 + ): + raise ValueError("A scaling factor must be a positive integer rational.") + return Fraction(numerator, denominator) + + +def _source_table(table: Mapping) -> dict: + """Reconstruct the source declaration a scaled table was derived from.""" + + source = { + key: copy.deepcopy(value) + for key, value in table.items() + if key not in _SCALED_TABLE_FIELDS + } + source["first_lower_cut_cents"] = table["source_first_lower_cut_cents"] + bands = [] + for band in table["bands"]: + row = {key: copy.deepcopy(value) for key, value in band.items()} + if "source_upper_cent" in row: + row["upper_cent"] = row.pop("source_upper_cent") + bands.append(row) + source["bands"] = bands + return source + + +def _source_cuts(source: Mapping) -> dict: + return { + "first_lower_cut_cents": source["first_lower_cut_cents"], + "upper_cents": [ + band["upper_cent"] for band in source["bands"] if band["kind"] == "positive" + ], + } + + +def _cut_payload(table: IntervalTable) -> dict: + return { + "first_lower_cut_cents": _rational(table.cuts[0]), + "upper_cents": [_rational(cut) for cut in table.cuts[1:]] + [None], + } + + +def interval_table(value: object) -> IntervalTable: + """Validate one source or scaled table declaration.""" + + raw = _mapping(value, "interval table") + scaled = "scaling" in raw + required = _TABLE_FIELDS | (_SCALED_TABLE_FIELDS if scaled else frozenset()) + row = _closed(raw, required, _OPTIONAL_TABLE_FIELDS, "interval table") + table_id = _text(row["id"], "Interval table id") + entity = _text(row["entity"], "Interval table entity") + _text(row["currency"], "Interval table currency") + _choice(row["input_unit"], INPUT_UNITS, "Interval table input_unit") + income = _text(row["income_column"], "Interval income column") + universe = _text(row["universe_column"], "Interval universe column") + if income == universe: + raise ValueError("Interval income and universe columns must differ.") + _period(row["source_period"], "Interval source period") + _period(row["target_period"], "Interval target period") + closure = _choice( + row["positive_band_closure"], CLOSURES, "Interval positive_band_closure" + ) + nil_present = ( + _choice(row["nil_band"], NIL_BAND_STATES, "Interval nil_band") == "present" + ) + policy = _choice( + row["negative_income_policy"], + NEGATIVE_INCOME_POLICIES, + "Interval negative_income_policy", + ) + _text(row["source_locator"], "Interval source locator") + if "description" in row: + _text(row["description"], "Interval table description") + diagnostics = _closed( + row["diagnostics"], _DIAGNOSTIC_FIELDS, frozenset(), "interval diagnostics" + ) + window = diagnostics["boundary_window_cents"] + if type(window) is not int or window < 0: + raise ValueError("boundary_window_cents must be a nonnegative integer.") + if diagnostics["alternative_positive_band_closure"] != alternative_closure(closure): + raise ValueError( + "The diagnostic alternative must be the other positive band closure." + ) + bands = row["bands"] + if not isinstance(bands, list) or not bands: + raise ValueError("An interval table needs a nonempty band list.") + if scaled: + first = _rational_cents(row["first_lower_cut_cents"], "Scaled first lower cut") + else: + first = Fraction( + _integer_cents(row["first_lower_cut_cents"], "First lower cut") + ) + if first < 0: + raise ValueError("The first lower cut must be nonnegative.") + band_ids, indicators, cuts, positive = [], [], [first], [] + nil_index, open_tail = None, False + companions = set() + for index, raw_band in enumerate(bands): + optional = _OPTIONAL_BAND_FIELDS + if scaled: + optional = optional | {"source_upper_cent"} + band = _mapping(raw_band, "interval band") + kind = band.get("kind") + required_band = _BAND_FIELDS | ( + {"upper_cent"} if kind == "positive" else frozenset() + ) + band = _closed(band, frozenset(required_band), optional, "interval band") + band_ids.append(_text(band["id"], "Interval band id")) + indicators.append(_text(band["indicator"], "Interval band indicator")) + if "source_label" in band: + _text(band["source_label"], "Interval band source label") + has_companions = tuple( + key in band for key in ("count_reference", "amount_reference") + ) + if has_companions not in {(True, True), (False, False)}: + raise ValueError("A band names both companion references or neither.") + companions.add(has_companions[0]) + if has_companions[0]: + _text(band["count_reference"], "Band count reference") + _text(band["amount_reference"], "Band amount reference") + if band["count_reference"] == band["amount_reference"]: + raise ValueError("A band's count and amount references must differ.") + if kind == "nil": + if not nil_present: + raise ValueError("A table declaring nil_band absent has a nil band.") + if index != 0: + raise ValueError("A nil band, when present, comes first.") + if "source_upper_cent" in band: + raise ValueError("A nil band has no cut.") + nil_index = index + continue + if kind != "positive": + raise ValueError("Interval band kind must be 'nil' or 'positive'.") + if open_tail: + raise ValueError("Exactly one final open tail ends the band list.") + positive.append(index) + upper = band["upper_cent"] + if upper is None: + open_tail = True + if scaled and band.get("source_upper_cent", 0) is not None: + raise ValueError("A scaled open tail keeps a null source cut.") + continue + if scaled: + value = _rational_cents(upper, "Scaled upper cut") + if "source_upper_cent" not in band: + raise ValueError("A scaled band keeps its source cut.") + else: + value = Fraction(_integer_cents(upper, "Upper cut")) + if value <= 0 or value <= cuts[-1]: + raise ValueError("Upper cuts must be positive and strictly increasing.") + cuts.append(value) + if nil_present and nil_index is None: + raise ValueError("A table declaring nil_band present needs a first nil band.") + if not open_tail: + raise ValueError( + "Exactly one final open tail with upper_cent null is required." + ) + if not positive: + raise ValueError("An interval table needs positive bands.") + if len(companions) != 1: + raise ValueError( + "A table's bands either all name companion references or none do." + ) + if len(set(band_ids)) != len(band_ids): + raise ValueError("Interval band ids must be unique within a table.") + if len(set(indicators)) != len(indicators) or {income, universe} & set(indicators): + raise ValueError("Interval band indicators must be unique output columns.") + table = IntervalTable( + id=table_id, + entity=entity, + income_column=income, + universe_column=universe, + closure=closure, + nil_present=nil_present, + negative_income_policy=policy, + window_cents=window, + band_ids=tuple(band_ids), + indicators=tuple(indicators), + nil_index=nil_index, + positive_indices=tuple(positive), + cuts=tuple(cuts), + scaled=scaled, + declaration=copy.deepcopy(row), + ) + if scaled: + _validate_scaling(table, row) + return table + + +def _validate_scaling(table: IntervalTable, row: Mapping) -> None: + scaling = _closed(row["scaling"], _SCALING_FIELDS, frozenset(), "interval scaling") + if scaling["operation"] != SCALING_OPERATION: + raise ValueError("Unknown interval scaling operation.") + _text(scaling["factor_id"], "Scaling factor id") + factor = _positive_factor(scaling["operational_factor"]) + for key in ( + "factor_declaration_sha256", + "factor_receipt_sha256", + "source_table_sha256", + "source_cuts_sha256", + ): + digest = scaling[key] + if ( + not isinstance(digest, str) + or len(digest) != 64 + or set(digest) - set("0123456789abcdef") + ): + raise ValueError(f"Scaling {key} must be a lowercase SHA-256.") + source = _source_table(row) + parsed = interval_table(source) + if parsed.scaled: + raise ValueError("A scaled table's source cannot itself be scaled.") + if ( + interval_document_sha256(source) != scaling["source_table_sha256"] + or interval_document_sha256(_source_cuts(source)) + != scaling["source_cuts_sha256"] + ): + raise ValueError("Scaled interval source table identity mismatch.") + expected = tuple(cut * factor for cut in parsed.cuts) + if expected != table.cuts: + raise ValueError( + "Scaled interval cuts must equal their source cuts times the factor " + "exactly once." + ) + + +def validate_interval_document(document: object) -> dict[str, IntervalTable]: + """Validate a whole document; return its tables by id in declared order.""" + + row = _closed( + document, + frozenset({"schema_version", "tables"}), + _DOCUMENT_FIELDS - {"schema_version", "tables"}, + "interval document", + ) + if ( + type(row["schema_version"]) is not int + or row["schema_version"] != INTERVAL_DOCUMENT_SCHEMA_VERSION + ): + raise ValueError("Interval documents require schema_version 1.") + for key in ("country", "description", "disclosure"): + if key in row: + _text(row[key], f"Interval document {key}") + tables = row["tables"] + if not isinstance(tables, list) or not tables: + raise ValueError("An interval document needs a nonempty table list.") + result: dict[str, IntervalTable] = {} + outputs, references = set(), [] + for raw in tables: + table = interval_table(raw) + if table.id in result: + raise ValueError("Interval table ids must be unique.") + result[table.id] = table + if outputs & set(table.indicators): + raise ValueError("Interval indicator ids must be unique.") + outputs.update(table.indicators) + for band in table.declaration["bands"]: + references.extend( + band[key] + for key in ("count_reference", "amount_reference") + if key in band + ) + if len(set(references)) != len(references): + raise ValueError("A companion reference belongs to at most one band.") + return result + + +def scale_interval_table( + table: Mapping, + factor: Mapping, + *, + factor_id: str, + factor_declaration_sha256: str, + factor_receipt_sha256: str, +) -> dict: + """Multiply every cut once by a positive rational; never round a cut.""" + + source = interval_table(table) + if source.scaled: + raise ValueError(f"Interval table {source.id!r} is already scaled.") + rational = _positive_factor(factor) + raw = copy.deepcopy(source.declaration) + scaled = { + key: value for key, value in raw.items() if key != "first_lower_cut_cents" + } + scaled["source_first_lower_cut_cents"] = raw["first_lower_cut_cents"] + first = Fraction(raw["first_lower_cut_cents"]) * rational + scaled["first_lower_cut_cents"] = _rational(first) + bands = [] + for band in raw["bands"]: + band = dict(band) + if band["kind"] == "positive": + cut = band["upper_cent"] + band["source_upper_cent"] = cut + band["upper_cent"] = None if cut is None else _rational(cut * rational) + bands.append(band) + scaled["bands"] = bands + scaled["scaling"] = { + "operation": SCALING_OPERATION, + "factor_id": factor_id, + # Recorded as declared (for example p / 10**digits), not reduced. + "operational_factor": { + "numerator": factor["numerator"], + "denominator": factor["denominator"], + }, + "factor_declaration_sha256": factor_declaration_sha256, + "factor_receipt_sha256": factor_receipt_sha256, + "source_table_sha256": interval_document_sha256(raw), + "source_cuts_sha256": interval_document_sha256(_source_cuts(raw)), + } + interval_table(scaled) + return scaled + + +def scale_interval_document( + document: Mapping, scalings: Mapping[str, Mapping[str, object]] +) -> dict: + """Return a document with only the named source tables scaled.""" + + tables = validate_interval_document(document) + if any(table.scaled for table in tables.values()): + raise ValueError("A base interval document cannot contain scaled tables.") + unknown = set(scalings) - set(tables) + if unknown: + raise ValueError(f"Unknown interval tables {sorted(unknown)}.") + effective = copy.deepcopy(dict(document)) + effective["tables"] = [ + scale_interval_table(raw, **scalings[raw["id"]]) + if raw["id"] in scalings + else raw + for raw in effective["tables"] + ] + validate_interval_document(effective) + return effective + + +def source_interval_table(table: Mapping) -> dict: + """The source declaration of a scaled table, or the table itself.""" + + parsed = interval_table(table) + return _source_table(parsed.declaration) if parsed.scaled else dict(table) + + +# --------------------------------------------------------------------------- +# Classification +# --------------------------------------------------------------------------- + + +def _amount_reason(value: object) -> str | None: + if isinstance(value, (bool, np.bool_)): + return "boolean_amount" + if isinstance(value, Integral): + return None + if value is None: + return "missing_amount" + if isinstance(value, float): + if math.isnan(value): + return "missing_amount" + return "non_integer_amount" if math.isfinite(value) else "nonfinite_amount" + if isinstance(value, str): + return "text_amount" + try: + if value != value: # pandas NA, numpy NaN scalars + return "missing_amount" + except TypeError: + return "missing_amount" + return "non_integer_amount" + + +def _validated( + table: IntervalTable, amounts: Sequence[object], universe: Sequence[object] +) -> list[int | None]: + """Validate every record, then return floored cents or None when excluded.""" + + amounts, universe = list(amounts), list(universe) + if len(amounts) != len(universe): + raise ValueError("Interval amounts and universe statuses must align.") + reasons, statuses, floored = Counter(), Counter(), [] + for amount, status in zip(amounts, universe, strict=True): + if not isinstance(status, str) or status not in UNIVERSE_STATES: + reasons["invalid_universe_status"] += 1 + statuses["invalid"] += 1 + floored.append(None) + continue + statuses[status] += 1 + if status == "excluded": + floored.append(None) + continue + if status == "unresolved": + reasons["unresolved_universe_status"] += 1 + floored.append(None) + continue + reason = _amount_reason(amount) + if reason is not None: + reasons[reason] += 1 + floored.append(None) + continue + value = int(amount) + if value < 0 and table.negative_income_policy == "refuse": + reasons["negative_amount_refused"] += 1 + floored.append(None) + continue + floored.append(max(0, value)) + if reasons: + raise IntervalPreparationError( + { + "table": table.id, + "entity": table.entity, + "records": len(amounts), + "refused_records": sum(reasons.values()), + "reasons": dict(sorted(reasons.items())), + "universe_statuses": dict(sorted(statuses.items())), + } + ) + return floored + + +def _cuts_at_or_below(z: int, cuts: Sequence[Fraction], inclusive: bool) -> int: + """Count cuts ``c`` with ``c < z`` (or ``c <= z``) by cross-multiplication.""" + + low, high = 0, len(cuts) + while low < high: + middle = (low + high) // 2 + cut = cuts[middle] + scaled = z * cut.denominator + if cut.numerator < scaled or (inclusive and cut.numerator == scaled): + low = middle + 1 + else: + high = middle + return low + + +def _position(table: IntervalTable, z: int, closure: str) -> int: + if table.nil_present and z == 0: + return table.nil_index + # Right-closed bands are ``lower < z <= upper`` and the tail ``z > last``; + # left-closed bands are ``lower <= z < upper`` and the tail ``z >= last``. + count = _cuts_at_or_below(z, table.cuts, inclusive=closure == "left") + return BELOW_FIRST_CUT if count == 0 else table.positive_indices[count - 1] + + +def classify_records( + table: IntervalTable, + amounts: Sequence[object], + universe: Sequence[object], + *, + closure: str | None = None, +) -> tuple[int, ...]: + """Band index per record, ``BELOW_FIRST_CUT`` or ``EXCLUDED``. + + Every record is validated first; any refusal raises before a band is + computed. ``closure`` defaults to the table's own declaration. + """ + + closure = ( + table.closure if closure is None else _choice(closure, CLOSURES, "closure") + ) + floored = _validated(table, amounts, universe) + return tuple( + EXCLUDED if z is None else _position(table, z, closure) for z in floored + ) + + +def interval_indicators( + table: IntervalTable, amounts: Sequence[object], universe: Sequence[object] +) -> dict[str, np.ndarray]: + """One Boolean indicator per band, produced only after validation passes.""" + + positions = np.asarray(classify_records(table, amounts, universe), dtype=np.int64) + return { + indicator: positions == index + for index, indicator in enumerate(table.indicators) + } + + +def _fingerprint_value(value: object) -> object: + if isinstance(value, (bool, np.bool_)): + return ["bool", bool(value)] + if isinstance(value, Integral): + return int(value) + if isinstance(value, str): + return value + return [type(value).__name__, repr(value)] + + +def interval_input_fingerprint(values: Sequence[object]) -> str: + """Digest of an input column that keeps value types, including invalid ones.""" + + return interval_document_sha256([_fingerprint_value(value) for value in values]) + + +# --------------------------------------------------------------------------- +# Boundary diagnostics +# --------------------------------------------------------------------------- + + +def _record_order(record_ids: Sequence[object]) -> list: + result = [] + for value in record_ids: + if isinstance(value, (bool, np.bool_)) or not isinstance( + value, (str, Integral) + ): + raise ValueError("Diagnostic record identities are strings or integers.") + result.append(value if isinstance(value, str) else int(value)) + if len(set(result)) != len(result): + raise ValueError("Diagnostic record identities must be unique.") + return result + + +def boundary_diagnostics( + table: IntervalTable, + record_ids: Sequence[object], + amounts: Sequence[object], + universe: Sequence[object], + weights: Sequence[float], + *, + weight_record_ids: Sequence[object], + weight_kind: str, +) -> dict[str, object]: + """Fixed-weight boundary sensitivity, computed with exact weight arithmetic.""" + + order = _record_order(record_ids) + if _record_order(weight_record_ids) != order: + raise ValueError("Diagnostic weights are not aligned with the record order.") + values = np.asarray(weights, dtype=" 0 else "none" + ] + else: + destination = destinations["positive_bands"][ + table.band_ids[position] + ] + destination[0] += exact + destination[1] += exact * raw_negative + destination[2] += 1 + destination[3] += raw_negative + first = _cuts_at_or_below(z - window, table.cuts, inclusive=False) + last = _cuts_at_or_below(z + window, table.cuts, inclusive=True) + for index in range(first, last): + near[index][0] += exact + near[index][1] += 1 + cut_names = ["first_lower_cut"] + [ + table.band_ids[index] for index in table.positive_indices[:-1] + ] + source = _source_table(table.declaration) if table.scaled else table.declaration + source_cuts = _source_cuts(source) + source_values = [source_cuts["first_lower_cut_cents"], *source_cuts["upper_cents"]] + cuts = [ + { + "cut": name, + "cut_cents": _rational(cut), + "source_cut_cents": source_values[index], + "near_cut_weighted_count": _rational(near[index][0]), + "near_cut_records": near[index][1], + } + for index, (name, cut) in enumerate(zip(cut_names, table.cuts, strict=True)) + ] + + def measures(sums): + count, amount, records = sums + return { + "weighted_count": _rational(count), + "weighted_amount_cents": _rational(amount), + "records": records, + } + + def delta(slot): + return { + "weighted_count": _rational(other[slot][0] - declared[slot][0]), + "weighted_amount_cents": _rational(other[slot][1] - declared[slot][1]), + "records": other[slot][2] - declared[slot][2], + } + + def floored_measures(sums): + count, weighted_amount, records, amount = sums + return { + "records": records, + "weighted_count": _rational(count), + "pre_floor_amount_cents": amount, + "weighted_pre_floor_amount_cents": _rational(weighted_amount), + } + + def floored_by_destination(closure): + destinations = floored_destinations[closure] + return { + "nil": floored_measures(destinations["nil"]), + "below_first_cut": floored_measures(destinations["below_first_cut"]), + "none": floored_measures(destinations["none"]), + "positive_bands": { + band_id: floored_measures(sums) + for band_id, sums in destinations["positive_bands"].items() + }, + } + + if table.nil_index is not None and ( + declared[table.nil_index] != other[table.nil_index] + ): + raise ValueError("The nil band must be identical under both closures.") + bands = [] + for index, band_id in enumerate(table.band_ids): + row = { + "band": band_id, + "kind": "nil" if index == table.nil_index else "positive", + "declared": measures(declared[index]), + } + if index != table.nil_index: + row["alternative"] = measures(other[index]) + row["delta"] = delta(index) + bands.append(row) + scaling = table.declaration.get("scaling") + return { + "schema_version": 1, + "kind": "interval_boundary_diagnostics", + "table": table.id, + "entity": table.entity, + "currency": table.declaration["currency"], + "input_unit": table.declaration["input_unit"], + "positive_band_closure": table.closure, + "alternative_positive_band_closure": alternative, + "nil_band": "present" if table.nil_present else "absent", + "negative_income_policy": table.negative_income_policy, + "boundary_window_cents": window, + "weight_kind": weight_kind, + "records": len(order), + "included_records": included, + "digests": { + "table_sha256": interval_document_sha256(table.declaration), + "source_cuts_sha256": interval_document_sha256(source_cuts), + "effective_cuts_sha256": interval_document_sha256(_cut_payload(table)), + "factor": None + if scaling is None + else { + key: scaling[key] + for key in ( + "factor_id", + "operational_factor", + "factor_declaration_sha256", + "factor_receipt_sha256", + ) + }, + "weights_sha256": hashlib.sha256(values.tobytes()).hexdigest(), + "record_order_sha256": interval_document_sha256(order), + }, + "cuts": cuts, + "bands": bands, + "below_first_cut": { + "declared": measures(declared[BELOW_FIRST_CUT]), + "alternative": measures(other[BELOW_FIRST_CUT]), + "delta": delta(BELOW_FIRST_CUT), + }, + "floored_negative_income": { + **floored_measures(floored_negative), + "by_destination": { + "declared": floored_by_destination(table.closure), + "alternative": floored_by_destination(alternative), + }, + }, + "publisher_reclassification": PUBLISHER_RECLASSIFICATION, + "limitation": LIMITATION, + } + + +def frame_boundary_diagnostics(table: IntervalTable, frame) -> dict[str, object]: + """Diagnostics on a frame, weighted through ``resolve_weights(entity)``.""" + + data = frame.table(table.entity) + for column in (table.income_column, table.universe_column): + if column not in data: + raise ValueError( + f"Interval diagnostics need {table.entity}.{column} on the frame." + ) + weights = frame.resolve_weights(table.entity) + ids = data[frame.schema.entity_id_column(table.entity)].tolist() + return boundary_diagnostics( + table, + ids, + data[table.income_column].tolist(), + data[table.universe_column].tolist(), + weights.values, + weight_record_ids=ids, + weight_kind=weights.kind.value, + ) diff --git a/packages/microcosm-build/src/microcosm/build/reference_profiles.py b/packages/microcosm-build/src/microcosm/build/reference_profiles.py index 9a11ac22af..5354a795bc 100644 --- a/packages/microcosm-build/src/microcosm/build/reference_profiles.py +++ b/packages/microcosm-build/src/microcosm/build/reference_profiles.py @@ -19,7 +19,13 @@ from microcosm.graph.canonical import canonical_json REFERENCE_PROFILE_RESOLVER_VERSION = "reference-profiles-v1" +FACTOR_REFERENCE_PROFILE_RESOLVER_VERSION = "reference-profiles-v2" +ALLOWED_REFERENCE_PROFILE_RESOLVER_VERSIONS = frozenset( + {REFERENCE_PROFILE_RESOLVER_VERSION, FACTOR_REFERENCE_PROFILE_RESOLVER_VERSION} +) +SCALE_MONEY_AND_INTERVALS = "scale_money_and_intervals" REQUIRES_REFERENCE_PROFILE_RESOLUTION = "requires_reference_profile_resolution" +REQUIRES_PREREQUISITES = "requires_prerequisites" REFERENCE_DOCUMENT_KEYS = frozenset( {"country", "schema_version", "hierarchy", "target_references"} ) @@ -47,7 +53,7 @@ def _sequence(value: object, context: str) -> list: def _selection_identity(receipt: Mapping) -> dict: - return { + identity = { key: receipt[key] for key in ( "resolver_version", @@ -57,6 +63,394 @@ def _selection_identity(receipt: Mapping) -> dict: "selection", ) } + if receipt.get("resolver_version") == FACTOR_REFERENCE_PROFILE_RESOLVER_VERSION: + identity["selected_factor_identities"] = receipt["selected_factor_identities"] + identity["factor_companions_sha256"] = receipt["factor_companions_sha256"] + identity["transformed_names"] = receipt["transformed_names"] + if "interval_tables" in receipt: + identity["interval_tables_sha256"] = receipt["interval_tables_sha256"] + return identity + + +def validate_reference_factor_evidence(receipt: Mapping) -> dict: + """Bind selected declarations and receipts without claiming feed authenticity.""" + from microcosm.build.reference_factors import validate_factor_context + + if receipt.get("resolver_version") == REFERENCE_PROFILE_RESOLVER_VERSION: + if any( + key in receipt + for key in ( + "selected_factors", + "selected_factor_identities", + "factor_companions", + "factor_companions_sha256", + ) + ): + raise ValueError("Legacy resolution cannot carry factor evidence.") + return {} + factors = _mapping(receipt.get("selected_factors"), "selected factors") + if not factors: + raise ValueError("Factor resolution needs selected factor evidence.") + validated = validate_factor_context( + {"schema_version": 1, "factors": list(factors.values())}, list(factors) + ) + if validated != factors: + raise ValueError("Selected factor identities do not match their declarations.") + identities = { + factor_id: { + "declaration_sha256": reference_document_sha256(entry["declaration"]), + "receipt_sha256": entry["receipt"]["receipt_sha256"], + } + for factor_id, entry in sorted(factors.items()) + } + if identities != receipt.get("selected_factor_identities"): + raise ValueError("Selected factor evidence identity mismatch.") + return validated + + +def _profile_metadata(transform: Mapping) -> dict: + metadata = _mapping(transform.get("metadata", {}), "profile metadata") + if any( + not isinstance(key, str) or not isinstance(value, str) or not value + for key, value in metadata.items() + ): + raise ValueError("Profile metadata requires nonempty strings.") + if set(metadata) & { + "activation_status", + "activation_reason", + "parking_reason", + "required_reference_profile", + "required_measurement_binding", + "reference_value_kind", + "reference_prerequisites", + "reference_prerequisites_remaining", + "reference_selection_sha256", + "effective_intervals_sha256", + "reference_profiles_resolved", + }: + raise ValueError("A profile cannot override resolution identities.") + return metadata + + +def _explicit_names(transform: Mapping, field: str) -> list[str]: + names = _sequence(transform.get(field), field) + if ( + not names + or any(not isinstance(name, str) or not name for name in names) + or len(set(names)) != len(names) + ): + raise ValueError("A transformation needs unique explicit reference names.") + return names + + +def _companion_key(row: Mapping, *, scope: bool = False) -> bytes: + selector = _mapping(row.get("ledger_selector"), "companion selector") + excluded = {"aggregate_fact_key", "source_record_id"} + if not scope: + excluded.update({"source_measure_id", "source_concept"}) + else: + excluded.add("dimension_values") + payload = { + "selector": { + key: value for key, value in selector.items() if key not in excluded + }, + "entity": row.get("entity"), + "period": row.get("period"), + "reference_set": row.get("metadata", {}).get("reference_set"), + } + if not scope: + payload["filter"] = row.get("filter") + return canonical_json(payload) + + +def _validate_companions(transform: Mapping, by_name: Mapping) -> tuple[list, list]: + money = _explicit_names(transform, "reference_names") + counts = _explicit_names(transform, "count_reference_names") + if set(money) & set(counts) or len(money) != len(counts): + raise ValueError("Money and count rosters need disjoint complete companions.") + for kind, names in (("money", money), ("count", counts)): + if set(names) - set(by_name): + raise ValueError("A profile names missing companion references.") + if any( + by_name[name].get("metadata", {}).get("reference_value_kind") != kind + for name in names + ): + raise ValueError( + "Money and count rosters require matching declared value kinds." + ) + scopes = {_companion_key(by_name[name], scope=True) for name in names} + complete = { + name + for name, row in by_name.items() + if isinstance(row.get("ledger_selector"), Mapping) + and _companion_key(row, scope=True) in scopes + } + if complete != set(names): + raise ValueError("Money and count rosters are incomplete companions.") + money_keys = [_companion_key(by_name[name]) for name in money] + count_keys = [_companion_key(by_name[name]) for name in counts] + if len(set(money_keys)) != len(money) or set(money_keys) != set(count_keys): + raise ValueError("Money and count rosters must match one-to-one companions.") + if {_companion_key(by_name[name], scope=True) for name in money} & { + _companion_key(by_name[name], scope=True) for name in counts + }: + raise ValueError("Money and count companions must select distinct measures.") + return money, counts + + +def _factor_companions(chosen: Mapping, by_name: Mapping) -> dict: + """Capture roster roles and source value semantics before transforming rows.""" + companions = {} + for dimension, choice in chosen.items(): + for transform in choice["declaration"].get("transformations", []): + if transform.get("operation") != SCALE_MONEY_AND_INTERVALS: + continue + money, counts = _validate_companions(transform, by_name) + for role, names in (("money", money), ("count", counts)): + for name in names: + if name in companions: + raise ValueError("Duplicate factor companion roster entry.") + row = by_name[name] + companions[name] = { + "role": role, + "factor_id": transform["factor_id"], + "dimension": dimension, + "profile": choice["name"], + "source": _copy( + { + "ledger_selector": row["ledger_selector"], + "period": row.get("period"), + "value_operation": row.get( + "value_operation", "identity" + ), + "value_operands": row.get("value_operands", []), + "metadata": { + "reference_value_kind": row["metadata"][ + "reference_value_kind" + ] + }, + } + ), + } + return companions + + +def _interval_table_ids(transform: Mapping) -> list[str]: + tables = _sequence(transform.get("interval_table_ids"), "interval table ids") + if any(not isinstance(table, str) or not table for table in tables) or len( + set(tables) + ) != len(tables): + raise ValueError("Interval table ids must be unique nonempty text.") + return tables + + +def _validate_interval_companions( + transform: Mapping, tables: Mapping, by_name: Mapping, declaration: Mapping +) -> None: + """Every scaled band names exactly one count/money companion pair.""" + money, counts = _validate_companions(transform, by_name) + band_money, band_counts = [], [] + for table_id in _interval_table_ids(transform): + table = tables[table_id] + if ( + table.declaration["source_period"] != declaration["source_period"] + or table.declaration["target_period"] != declaration["target_period"] + ): + raise ValueError( + "Factor and interval table source/target periods are incompatible." + ) + for band in table.declaration["bands"]: + if "count_reference" not in band: + raise ValueError( + "An interval table without companion references cannot be scaled." + ) + pair = (band["count_reference"], band["amount_reference"]) + for name in pair: + row = by_name.get(name) + if ( + row is None + or row.get("entity") != table.entity + or row.get("filter") != band["indicator"] + ): + raise ValueError( + "Interval companions must filter on their band indicator." + ) + if _companion_key(by_name[pair[0]]) != _companion_key(by_name[pair[1]]): + raise ValueError( + "A band's count and money references are not companions." + ) + band_counts.append(pair[0]) + band_money.append(pair[1]) + if ( + len(set(band_money)) != len(band_money) + or len(set(band_counts)) != len(band_counts) + or set(band_money) != set(money) + or set(band_counts) != set(counts) + ): + raise ValueError( + "Interval band companions must be exactly the money and count rosters." + ) + + +def _scaled_intervals( + chosen: Mapping, + intervals: Mapping | None, + by_name: Mapping, + selected_factors: Mapping, +) -> tuple[dict | None, dict]: + """Scale each named table once with its transformation's selected factor.""" + requests = {} + for dimension, choice in chosen.items(): + for transform in choice["declaration"].get("transformations", []): + if transform.get("operation") != SCALE_MONEY_AND_INTERVALS: + continue + for table_id in _interval_table_ids(transform): + if table_id in requests: + raise ValueError( + f"Interval table {table_id!r} is scaled by more than one " + "transformation." + ) + requests[table_id] = (dimension, choice["name"], transform) + if not requests: + return intervals, {} + if intervals is None: + raise ValueError("Interval scaling needs the declared interval document.") + from microcosm.build.reference_intervals import ( + scale_interval_document, + validate_interval_document, + ) + + tables = validate_interval_document(intervals) + if set(requests) - set(tables): + raise ValueError("A profile names an undeclared interval table.") + scalings, records, checked = {}, {}, set() + for table_id, (dimension, profile, transform) in sorted(requests.items()): + factor_id = transform["factor_id"] + entry = selected_factors[factor_id] + if id(transform) not in checked: + _validate_interval_companions( + transform, tables, by_name, entry["declaration"] + ) + checked.add(id(transform)) + scalings[table_id] = { + "factor": entry["operational_factor"], + "factor_id": factor_id, + "factor_declaration_sha256": reference_document_sha256( + entry["declaration"] + ), + "factor_receipt_sha256": entry["receipt"]["receipt_sha256"], + } + records[table_id] = { + "dimension": dimension, + "profile": profile, + "factor_id": factor_id, + "operational_factor": _copy(entry["operational_factor"]), + "source_table_sha256": reference_document_sha256( + tables[table_id].declaration + ), + "bands": len(tables[table_id].band_ids), + } + effective = scale_interval_document(intervals, scalings) + for raw in effective["tables"]: + if raw["id"] in records: + records[raw["id"]]["effective_table_sha256"] = reference_document_sha256( + raw + ) + return effective, records + + +def _validate_interval_resolution( + resolution: Mapping, factors: Mapping, interval_document: Mapping | None +) -> None: + """Bind recorded interval scaling to selected factors and the document.""" + records = resolution.get("interval_tables") + if records is None: + if "interval_tables_sha256" in resolution or resolution.get( + "effective_intervals_sha256" + ) != resolution.get("base_intervals_sha256"): + raise ValueError( + "Unscaled effective intervals must equal their base document." + ) + return + records = _mapping(records, "interval scaling records") + if ( + resolution.get("resolver_version") != FACTOR_REFERENCE_PROFILE_RESOLVER_VERSION + or not records + or reference_document_sha256(records) + != resolution.get("interval_tables_sha256") + or resolution.get("effective_intervals_sha256") + == resolution.get("base_intervals_sha256") + ): + raise ValueError("Interval scaling record identity mismatch.") + identities = resolution.get("selected_factor_identities", {}) + for record in records.values(): + record = _mapping(record, "interval scaling record") + factor_id = record.get("factor_id") + if ( + factor_id not in factors + or record.get("operational_factor") + != factors[factor_id]["operational_factor"] + or record.get("profile") + != resolution["selection"].get(record.get("dimension")) + ): + raise ValueError("Interval scaling disagrees with its selected factor.") + if interval_document is None: + return + from microcosm.build.reference_intervals import validate_interval_document + + tables = validate_interval_document(interval_document) + scaled = {table_id for table_id, table in tables.items() if table.scaled} + if scaled != set(records): + raise ValueError("Effective interval tables differ from their scaling records.") + for table_id in scaled: + record, declaration = records[table_id], tables[table_id].declaration + scaling = declaration["scaling"] + identity = identities.get(record["factor_id"], {}) + if ( + reference_document_sha256(declaration) + != record.get("effective_table_sha256") + or scaling["source_table_sha256"] != record.get("source_table_sha256") + or scaling["factor_id"] != record["factor_id"] + or scaling["operational_factor"] != record["operational_factor"] + or scaling["factor_receipt_sha256"] != identity.get("receipt_sha256") + or scaling["factor_declaration_sha256"] + != identity.get("declaration_sha256") + ): + raise ValueError("Effective interval table scaling identity mismatch.") + + +def _satisfy_factor_prerequisite(row: dict, dimension: str, binding: str) -> list: + metadata = row.setdefault("metadata", {}) + if metadata.get("activation_status") != REQUIRES_PREREQUISITES: + raise ValueError( + "Money scaling requires the explicit prerequisite parking status." + ) + if ( + metadata.get("required_reference_profile") != dimension + or metadata.get("required_measurement_binding") != binding + ): + raise ValueError("Money scaling has incompatible reference prerequisites.") + try: + prerequisites = json.loads(metadata.get("reference_prerequisites", "")) + except (TypeError, ValueError) as error: + raise ValueError( + "Reference prerequisites must be an explicit JSON list." + ) from error + required = {f"reference_profile:{dimension}", f"measurement:{binding}"} + if ( + not isinstance(prerequisites, list) + or any(not isinstance(item, str) or not item for item in prerequisites) + or len(set(prerequisites)) != len(prerequisites) + or set(prerequisites) != required + ): + raise ValueError( + "Reference prerequisites must name the profile and measurement." + ) + remaining = [ + item for item in prerequisites if item != f"reference_profile:{dimension}" + ] + metadata["reference_prerequisites_remaining"] = canonical_json(remaining).decode() + return remaining def resolve_reference_profiles( @@ -64,13 +458,17 @@ def resolve_reference_profiles( profile_declarations: Mapping, selection: Mapping, interval_document: Mapping | None = None, + *, + factor_context: Mapping | None = None, ) -> tuple[dict, dict | None, dict]: """Return effective references, effective intervals and a bound receipt. Only selected declarations enter selection identity. An unavailable profile refuses; an explicitly deferred dimension is reported without claiming its - transformations ran. Interval transformations are intentionally unsupported - until a consumer declares their complete transformation contract. + transformations ran. Money scaling consumes declared factor evidence; + compilation authenticates it against the feed. Named interval tables are + scaled by the same selected factor as their money companions; without + named tables the interval document passes through unchanged. Resource headers are bound into the base identity; effective references use the compiler's closed document shape. """ @@ -120,21 +518,74 @@ def resolve_reference_profiles( deferred.append(dimension) chosen[dimension] = {"name": name, "declaration": profile} resolved_selection[dimension] = name + factor_ids = set() + for choice in chosen.values(): + for raw_transform in choice["declaration"].get("transformations", []): + transform = _mapping(raw_transform, "reference transformation") + if transform.get("operation") == SCALE_MONEY_AND_INTERVALS: + _interval_table_ids(transform) + factor_id = transform.get("factor_id") + if not isinstance(factor_id, str) or not factor_id: + raise ValueError("Money scaling needs a declared factor id.") + factor_ids.add(factor_id) + selected_factors = {} + if factor_ids: + from microcosm.build.reference_factors import validate_factor_context + + selected_factors = validate_factor_context(factor_context, sorted(factor_ids)) + base_intervals_hash = ( + None if intervals is None else reference_document_sha256(intervals) + ) + intervals, interval_records = _scaled_intervals( + chosen, intervals, by_name, selected_factors + ) receipt = { "resolver_version": REFERENCE_PROFILE_RESOLVER_VERSION, "base_references_sha256": reference_document_sha256(base), - "base_intervals_sha256": ( - None if intervals is None else reference_document_sha256(intervals) - ), + "base_intervals_sha256": base_intervals_hash, "selected_declarations_sha256": reference_document_sha256(chosen), "selection": resolved_selection, } + if selected_factors: + companions = _factor_companions(chosen, by_name) + receipt.update( + resolver_version=FACTOR_REFERENCE_PROFILE_RESOLVER_VERSION, + factor_companions=companions, + factor_companions_sha256=reference_document_sha256(companions), + transformed_names=sorted( + name + for choice in chosen.values() + for transform in choice["declaration"].get("transformations", []) + for field in ( + ("reference_names", "count_reference_names") + if transform.get("operation") == SCALE_MONEY_AND_INTERVALS + else ("reference_names",) + ) + for name in _explicit_names(transform, field) + ), + selected_factors=_copy(selected_factors), + selected_factor_identities={ + factor_id: { + "declaration_sha256": reference_document_sha256( + entry["declaration"] + ), + "receipt_sha256": entry["receipt"]["receipt_sha256"], + } + for factor_id, entry in sorted(selected_factors.items()) + }, + ) + if interval_records: + receipt.update( + interval_tables=interval_records, + interval_tables_sha256=reference_document_sha256(interval_records), + ) selection_hash = reference_document_sha256(_selection_identity(receipt)) interval_hash = None if intervals is None else reference_document_sha256(intervals) transformed, policies = {}, [] for dimension, choice in chosen.items(): for raw_transform in choice["declaration"].get("transformations", []): transform = _mapping(raw_transform, "reference transformation") + operation = transform.get("operation") allowed = { "reference_names", "operation", @@ -143,30 +594,108 @@ def resolve_reference_profiles( "notes", "target_label", } + if operation == SCALE_MONEY_AND_INTERVALS: + allowed = { + "reference_names", + "count_reference_names", + "operation", + "factor_id", + "interval_table_ids", + "required_measurement_binding", + "metadata", + } if set(transform) - allowed: raise ValueError("Unknown reference transformation fields.") - if transform.get("operation") != ALLOCATED_RESIDUAL_BY_RATIO: + if operation not in { + ALLOCATED_RESIDUAL_BY_RATIO, + SCALE_MONEY_AND_INTERVALS, + }: raise ValueError("Unsupported reference profile transformation.") + metadata = _profile_metadata(transform) + if _carried_value_keys(transform): + raise ValueError("Reference transformations carry observed values.") + if operation == SCALE_MONEY_AND_INTERVALS: + binding = transform.get("required_measurement_binding") + if not isinstance(binding, str) or not binding: + raise ValueError( + "Money scaling needs a required measurement binding." + ) + money, counts = _validate_companions(transform, by_name) + factor_id = transform["factor_id"] + factor = selected_factors[factor_id] + declaration = factor["declaration"] + if declaration["purpose"] != "profile_input": + raise ValueError("A diagnostic factor cannot be a profile input.") + rational = factor["operational_factor"] + weight = rational["numerator"] / rational["denominator"] + for name in [*money, *counts]: + if name in transformed: + raise ValueError( + f"Duplicate or incompatible transformation: {name!r}." + ) + row = by_name[name] + if ( + row.get("ledger_selector", {}).get("period_value") + != declaration["source_period"] + or row.get("period") != declaration["target_period"] + ): + raise ValueError( + "Factor and reference source/target periods are incompatible." + ) + remaining = _satisfy_factor_prerequisite(row, dimension, binding) + if name in money: + if row.get( + "value_operation", "identity" + ) != "identity" or row.get("value_operands", []): + raise ValueError( + "Money scaling requires an untransformed source reference." + ) + selector = _mapping( + row.get("ledger_selector"), "money selector" + ) + key = selector.get("aggregate_fact_key") + if not isinstance(key, str) or not key: + raise ValueError( + "Money scaling needs a singleton source fact key." + ) + row["value_operation"] = "linear_combination" + row["value_operands"] = [ + { + "aggregate_fact_key": key, + "expected_member_count": 1, + "weight": weight, + } + ] + row_metadata = row.setdefault("metadata", {}) + row_metadata.update(metadata) + row_metadata["reference_selection_sha256"] = selection_hash + row_metadata["reference_profiles_resolved"] = "1" + if interval_hash is not None: + row_metadata["effective_intervals_sha256"] = interval_hash + transformed[name] = { + "dimension": dimension, + "profile": choice["name"], + "operation": "linear_combination" + if name in money + else "identity", + "factor_id": factor_id, + "operational_factor": _copy(rational), + "metadata": metadata, + "operand_selectors": _copy(row.get("value_operands", [])), + "source_period": row.get("ledger_selector", {}).get( + "period_value" + ), + "target_period": row.get("period"), + "unresolved_prerequisites": remaining, + } + policies.append( + {"dimension": dimension, "profile": choice["name"], **metadata} + ) + continue names = _sequence(transform.get("reference_names"), "transformed names") if not names or any(not isinstance(name, str) for name in names): raise ValueError("A transformation needs explicit reference names.") operands = _sequence(transform.get("value_operands"), "value operands") - metadata = _mapping(transform.get("metadata", {}), "profile metadata") - if any( - not isinstance(key, str) or not isinstance(value, str) or not value - for key, value in metadata.items() - ): - raise ValueError("Profile metadata requires nonempty strings.") - if set(metadata) & { - "activation_status", - "required_reference_profile", - "reference_selection_sha256", - "effective_intervals_sha256", - "reference_profiles_resolved", - }: - raise ValueError("A profile cannot override resolution identities.") - if _carried_value_keys(transform): - raise ValueError("Reference transformations carry observed values.") for name in names: if name not in by_name: raise ValueError(f"Profile names missing reference {name!r}.") @@ -233,6 +762,32 @@ def resolve_reference_profiles( return effective, intervals, receipt +def _factor_reference_bindings(resolution: Mapping) -> dict: + """Validate the compact roster bound into the v2 selection identity.""" + if resolution["resolver_version"] == REFERENCE_PROFILE_RESOLVER_VERSION: + return {} + bindings = _mapping(resolution.get("factor_companions"), "factor companions") + if reference_document_sha256(bindings) != resolution.get( + "factor_companions_sha256" + ): + raise ValueError("Factor companion source record identity mismatch.") + for name, raw_binding in bindings.items(): + binding = _mapping(raw_binding, "factor companion") + source = _mapping(binding.get("source"), "factor companion source") + if ( + not isinstance(name, str) + or not name + or binding.get("role") not in {"money", "count"} + or binding.get("profile") + != resolution["selection"].get(binding.get("dimension")) + or source.get("metadata", {}).get("reference_value_kind") != binding["role"] + ): + raise ValueError( + "Factor companion roster role or profile identity mismatch." + ) + return bindings + + def validate_reference_resolution( document: Mapping, receipt: Mapping, @@ -240,14 +795,25 @@ def validate_reference_resolution( references_sha256: str | None = None, interval_document: Mapping | None = None, ) -> dict: - """Refuse stale effective documents, receipts or interval companions.""" + """Refuse stale effective documents, receipts or interval companions. + + The checks bind the effective rows to the receipt and the receipt's + factor companions to its selection identity. They assume that identity is + trusted, as when composition resolves a fresh receipt: a forger who also + replaces the selection identity is outside this layer. Selected factors + are anchored independently by replay against the authenticated feed. + """ resolution = _copy(_mapping(receipt, "reference resolution receipt")) - if resolution.get("resolver_version") != REFERENCE_PROFILE_RESOLVER_VERSION: + if ( + resolution.get("resolver_version") + not in ALLOWED_REFERENCE_PROFILE_RESOLVER_VERSIONS + ): raise ValueError("Unknown reference resolver version.") claimed_receipt_hash = resolution.pop("receipt_sha256", None) if claimed_receipt_hash != reference_document_sha256(resolution): raise ValueError("Reference resolution receipt hash mismatch.") resolution["receipt_sha256"] = claimed_receipt_hash + factors = validate_reference_factor_evidence(resolution) actual = reference_document_sha256(document) if actual != resolution.get("effective_references_sha256") or ( references_sha256 is not None and actual != references_sha256 @@ -263,16 +829,115 @@ def validate_reference_resolution( interval_document ) != resolution.get("effective_intervals_sha256"): raise ValueError("Effective interval document hash mismatch.") - names = [] + _validate_interval_resolution(resolution, factors, interval_document) + factor_bindings = _factor_reference_bindings(resolution) + transformed_names = resolution.get("transformed_names") + if not isinstance(transformed_names, list) or not all( + isinstance(name, str) for name in transformed_names + ): + raise ValueError("Resolution receipt transformed names are malformed.") + transformations = _mapping( + resolution.get("transformations"), "resolution transformations" + ) + if any(not isinstance(action, Mapping) for action in transformations.values()): + raise ValueError("Resolution transformations must map names to objects.") + other_names = set(transformed_names) - set(factor_bindings) + names, used_factors, seen_names = [], set(), set() for row in document.get("target_references", ()): + name = row.get("name") metadata = row.get("metadata", {}) - if metadata.get("reference_profiles_resolved"): - names.append(row["name"]) + resolved = metadata.get("reference_profiles_resolved") + if (factors or resolved) and (not isinstance(name, str) or not name): + raise ValueError( + "Resolved and factor reference names must be nonempty strings." + ) + if factors: + if name in seen_names: + raise ValueError("Duplicate factor companion reference roster name.") + seen_names.add(name) + if resolved: + names.append(name) if metadata.get("reference_selection_sha256") != selection_hash or ( metadata.get("effective_intervals_sha256") != resolution.get("effective_intervals_sha256") ): raise ValueError("Effective reference profile identity mismatch.") + action = transformations.get(name, {}) + binding = factor_bindings.get(name) + if factors and binding is None and name not in other_names: + raise ValueError( + "Factor action names a row outside its companion roster." + ) + if binding is not None or "factor_id" in action: + if binding is None: + raise ValueError( + "Factor action names a row outside its companion roster." + ) + role = binding["role"] + operation = "linear_combination" if role == "money" else "identity" + if action.get("operation") != operation or any( + action.get(key) != binding[key] + for key in ("dimension", "profile", "factor_id") + ): + raise ValueError( + "Factor action disagrees with its companion roster role." + ) + source = binding["source"] + if ( + metadata.get("reference_value_kind") != role + or row.get("ledger_selector") != source.get("ledger_selector") + or row.get("period") != source.get("period") + ): + raise ValueError( + "Effective factor companion source semantics changed." + ) + factor_id = binding["factor_id"] + if factor_id not in factors: + raise ValueError( + "A transformed reference has missing factor evidence." + ) + used_factors.add(factor_id) + entry = factors[factor_id] + declaration = entry["declaration"] + rational = entry["operational_factor"] + if ( + action.get("operational_factor") != rational + or action.get("source_period") != declaration["source_period"] + or action.get("target_period") != declaration["target_period"] + ): + raise ValueError("Effective reference factor identity mismatch.") + if role == "money": + expected = [ + { + "aggregate_fact_key": source.get("ledger_selector", {}).get( + "aggregate_fact_key" + ), + "expected_member_count": 1, + "weight": rational["numerator"] / rational["denominator"], + } + ] + if ( + row.get("value_operation") != "linear_combination" + or row.get("value_operands") != expected + or action.get("operand_selectors") != expected + ): + raise ValueError( + "Effective money factor must be applied exactly once." + ) + elif ( + row.get("value_operation", "identity") + != source.get("value_operation", "identity") + or row.get("value_operands", []) != source.get("value_operands", []) + or action.get("operand_selectors") + != source.get("value_operands", []) + ): + raise ValueError( + "Effective count value semantics must remain unchanged." + ) if sorted(names) != resolution.get("transformed_names"): raise ValueError("Resolution receipt transformed names mismatch.") + if used_factors != set(factors): + raise ValueError("Resolution receipt has unused selected factor evidence.") + if set(factor_bindings) - set(names): + raise ValueError("Resolution receipt is missing factor companion rows.") return resolution diff --git a/packages/microcosm-build/src/microcosm/build/transport/cli.py b/packages/microcosm-build/src/microcosm/build/transport/cli.py index 3d26dd15ff..6f42b3b0f8 100644 --- a/packages/microcosm-build/src/microcosm/build/transport/cli.py +++ b/packages/microcosm-build/src/microcosm/build/transport/cli.py @@ -14,6 +14,10 @@ explorer page and ``build-status.json``. The status file lists the outputs the spec declares as still owed by a later package. There is no upload, staging or publication path; ``--local-only`` is the only mode. + +The currency check guards new runs only: ``auto`` and ``forbid`` require +selected factors current on today's UTC date before CREATE; ``require`` only +verifies stored work. """ from __future__ import annotations @@ -24,6 +28,7 @@ import sys from collections.abc import Mapping, Sequence from dataclasses import dataclass, replace +from datetime import UTC, date, datetime from pathlib import Path from tempfile import TemporaryDirectory from types import MappingProxyType @@ -32,6 +37,7 @@ import pandas as pd from microcosm.build.artifact_files import file_artifact, materialize_bytes +from microcosm.build.reference_factors import require_current_factors from microcosm.frame import Frame from microcosm.frame.adapters.axiom import AxiomEntityTableDataset from microcosm.frame.materialize import put_frame_table @@ -60,6 +66,7 @@ TransportGraphExtension, compose_transport_graph, load_transport_spec, + reference_profile_views, skeleton_create_declaration, transport_endpoints, transport_pending_outputs, @@ -223,7 +230,12 @@ def prepare_transport_build( inventory_store: ContentStore | str | Path | None = None, resume: ResumePolicy = "auto", ) -> PreparedTransportBuild: - """Check activation, build the registry and CREATE inventory, then compose. + """Check factor currency and activation, then compose the prepared graph. + + A new run (``auto`` or ``forbid``) first requires every factor the default + and scenario views select to be current on today's UTC date; ``require`` + only verifies stored work. This is the run-entry check for every caller, + the CLI included. Composition and execution stay clock-free. Before registry preparation, CREATE or graph source reads, activation checks declaration resource paths, non-null selected roots and encoding @@ -241,9 +253,10 @@ def prepare_transport_build( CREATE sources and reuses the stored inventory without running the probe. """ - validate_transport_activation(spec) if resume not in {"auto", "require", "forbid"}: raise ValueError("resume must be 'auto', 'require' or 'forbid'.") + _require_current_run_factors(spec, resume=resume) + validate_transport_activation(spec) if resume == "require": root = ( inventory_store.root @@ -466,6 +479,9 @@ def execute_transport_graph( later checkpoints reuse this invocation's work. The skeleton H5 is rewritten only when the export descriptor changed; an unchanged H5 must pass readback, and under ``require`` it must already exist. + + Execution is clock-free. It runs a graph that :func:`prepare_transport_build` + checked; a caller that composes a graph itself owns the currency check. """ if resume not in {"auto", "require", "forbid"}: @@ -634,8 +650,34 @@ def parse_args(argv: Sequence[str] | None = None) -> argparse.Namespace: return args +def _today() -> date: + """Today's UTC date, so a local run and CI agree on a validity boundary.""" + return datetime.now(UTC).date() + + +def _require_current_run_factors( + spec: Mapping[str, object], *, resume: ResumePolicy +) -> None: + """The currency check guards new runs only, including scenario selections. + + ``require`` only replays stored work and may verify historical factors. + Check every factor the default and scenario views select, through the + walk activation uses, against today's UTC date, before CREATE. + """ + if resume == "require": + return + selected = {} + for view in reference_profile_views(spec): + selected.update(view[2].get("selected_factors", {})) + require_current_factors(selected, today=_today()) + + def main(argv: Sequence[str] | None = None) -> int: - """Run the CLI; return 0 on success and 1 on a refused build.""" + """Run the CLI; return 0 on success and 1 on a refused build. + + Preparation's currency check guards new runs only (``auto`` and + ``forbid``), before CREATE. ``require`` verifies existing stored work. + """ try: args = parse_args(argv) diff --git a/packages/microcosm-build/src/microcosm/build/transport/compose.py b/packages/microcosm-build/src/microcosm/build/transport/compose.py index 211cf380a9..4c7a91417c 100644 --- a/packages/microcosm-build/src/microcosm/build/transport/compose.py +++ b/packages/microcosm-build/src/microcosm/build/transport/compose.py @@ -68,7 +68,10 @@ ATOMIC_GEOGRAPHY_VALIDATION_TYPE, ATOMIC_SUPPORT_TYPE, ) -from microcosm.build.ledger_artifact import CHRONICLE_FEED_RESOURCE +from microcosm.build.ledger_artifact import ( + CHRONICLE_FEED_RESOURCE, + chronicle_feed_identity, +) from microcosm.build.reference_profiles import resolve_reference_profiles from microcosm.calibrate.ordered_kernels import OUTPUT_TYPES from microcosm.graph import ( @@ -386,14 +389,52 @@ def reference_profile_view( else {name: value for name, value in selection.items() if name in dimensions} ) intervals = declarations.get("interval_resource") - return resolve_reference_profiles( + factor_context_resource = declarations.get("factor_context_resource") + view = resolve_reference_profiles( _raw_transport_resource(spec, resource), declarations, selected, interval_document=None if intervals is None else _raw_transport_resource(spec, intervals), + factor_context=None + if factor_context_resource is None + else _raw_transport_resource(spec, factor_context_resource), ) + if _has_resource(spec, CHRONICLE_FEED_RESOURCE): + feed_pin = _raw_transport_resource(spec, CHRONICLE_FEED_RESOURCE) + for entry in view[2].get("selected_factors", {}).values(): + if entry["declaration"]["feed_identity"] != chronicle_feed_identity( + feed_pin + ): + raise ValueError( + "Selected factor context is incompatible with the declared feed." + ) + return view + + +def reference_profile_views(spec: Mapping[str, object]) -> tuple: + """Resolve the default profile view and each distinct scenario-knob view. + + Activation and run entry share this walk. Scenario views resolve only when + both ``reference_profiles`` and ``scenarios`` are declared; knob sets that + repeat, or equal the default selection, resolve once. + """ + view = reference_profile_view(spec) + if view is None: + return () + views = [view] + if _has_resource(spec, "scenarios"): + checked_selections = {canonical_json({})} + for scenario in _sequence( + _raw_transport_resource(spec, "scenarios").get("scenarios"), "scenarios" + ): + knobs = _mapping(_mapping(scenario, "scenario").get("knobs", {}), "knobs") + identity = canonical_json(knobs) + if identity not in checked_selections: + views.append(reference_profile_view(spec, knobs)) + checked_selections.add(identity) + return tuple(views) def transport_resource( @@ -535,7 +576,7 @@ def validate_transport_activation(spec: Mapping[str, object]) -> None: missing = [] # Resolve first so activation never inspects an executable profile's raw rows. - reference_profile_view(spec) + reference_profile_views(spec) selections = ( tuple(_declared_resource_selections(transport_resource(spec, GRAPH_RESOURCE))) if _has_resource(spec, GRAPH_RESOURCE) @@ -1199,9 +1240,17 @@ def _node( ): view = reference_profile_view(spec, profile_selection) if view is not None: - references, _, receipt = view + references, intervals, receipt = view if canonical_json(references).decode("utf-8") == params["references"]: params["reference_resolution"] = canonical_json(receipt).decode("utf-8") + # Preparation receives the exact effective interval companion. + if kernel == "calibration.prepare@1" and intervals is not None: + companion = canonical_json(intervals).decode("utf-8") + if params.setdefault("intervals", companion) != companion: + raise ValueError( + f"Node {row.get('id')!r} supplies an interval document " + "that differs from its effective interval companion." + ) if "rules_binding" in row: params = _rules_params(spec, row, params, config) elif kernel == RULES_ROUTER: diff --git a/packages/microcosm-build/src/microcosm/build/transport/target_kernels.py b/packages/microcosm-build/src/microcosm/build/transport/target_kernels.py index 2752a924a0..46f25de2fa 100644 --- a/packages/microcosm-build/src/microcosm/build/transport/target_kernels.py +++ b/packages/microcosm-build/src/microcosm/build/transport/target_kernels.py @@ -53,6 +53,8 @@ import microcosm.build.country_spec as country_spec_module import microcosm.build.ledger_artifact as ledger_artifact_module import microcosm.build.ledger_targets as ledger_targets_module +import microcosm.build.reference_factors as reference_factors_module +import microcosm.build.reference_intervals as reference_intervals_module import microcosm.build.reference_profiles as reference_profiles_module import microcosm.calibrate.artifacts as calibrate_artifacts_module import microcosm.calibrate.hierarchy as hierarchy_module @@ -71,7 +73,9 @@ compile_ledger_target_references, ) from microcosm.build.reference_profiles import ( + ALLOWED_REFERENCE_PROFILE_RESOLVER_VERSIONS, REFERENCE_DOCUMENT_KEYS, + validate_reference_factor_evidence, validate_reference_resolution, ) from microcosm.calibrate import TargetRegistry, TargetSpec @@ -274,8 +278,7 @@ def _surface_resolution(document: Mapping, registry: TargetRegistry) -> Mapping body = dict(resolution) claimed = body.pop("receipt_sha256", None) if ( - body.get("resolver_version") - != reference_profiles_module.REFERENCE_PROFILE_RESOLVER_VERSION + body.get("resolver_version") not in ALLOWED_REFERENCE_PROFILE_RESOLVER_VERSIONS or claimed != reference_profiles_module.reference_document_sha256(body) ): raise ValueError("Surface reference resolution receipt hash mismatch.") @@ -291,6 +294,7 @@ def _surface_resolution(document: Mapping, registry: TargetRegistry) -> Mapping ) from error if selection != resolution.get("reference_selection_sha256"): raise ValueError("Surface reference selection identity mismatch.") + validate_reference_factor_evidence(resolution) for spec in resolved: if spec.metadata.get( "reference_selection_sha256" @@ -396,8 +400,37 @@ def compile_target_surface( document, reference_resolution, references_sha256=references_sha256 ) artifact = load_ledger_consumer_artifact( - facts_path, expected_facts_sha256=expected_facts_sha256, feed_pin=feed_pin + facts_path, + expected_facts_sha256=expected_facts_sha256, + feed_pin=feed_pin, + lexical_floats=bool( + reference_resolution and reference_resolution.get("selected_factors") + ), ) + if reference_resolution is not None: + for entry in reference_resolution.get("selected_factors", {}).values(): + factor_feed_identity = ledger_artifact_module.chronicle_feed_identity( + feed_pin + if feed_pin is not None + else entry["declaration"]["feed_identity"] + ) + if feed_pin is None: + ledger_artifact_module.validate_chronicle_feed_pin( + artifact, factor_feed_identity + ) + if (artifact.manifest or {}).get( + "source_commit" + ) != factor_feed_identity["source_commit"]: + raise ValueError( + "Factor source commit cannot be authenticated without a feed pin." + ) + reference_factors_module.replay_reference_factor( + entry["declaration"], + artifact.facts, + factor_feed_identity, + entry["operational_factor"], + entry["receipt"], + ) registry = compile_ledger_target_references( artifact.facts, references, country=country ) @@ -489,6 +522,7 @@ def _optional_float(value: float) -> float | None: ledger_targets_module, ledger_artifact_module, chronicle_epoch_module, + reference_factors_module, reference_profiles_module, registry_module, target_module, @@ -524,6 +558,8 @@ def implementation_hash(self) -> str: graph_inputs, artifact_types, calibration_columns_module, + reference_intervals_module, + reference_factors_module, reference_profiles_module, dependencies=self.capabilities.dependencies, ) @@ -552,6 +588,12 @@ def run(self, context: KernelContext) -> KernelResult: bindings = canonical_document_param(context, self.ref, "bindings") document = canonical_document_param(context, self.ref, "references") digest = sha256_param(context, self.ref, "references_sha256") + # Parsed once: the receipt check and column preparation read one document. + intervals = ( + canonical_document_param(context, self.ref, "intervals") + if "intervals" in context.params + else None + ) resolution = None if "reference_resolution" in context.params: candidate = canonical_document_param( @@ -559,7 +601,7 @@ def run(self, context: KernelContext) -> KernelResult: ) if ( candidate.get("effective_intervals_sha256") is not None - and "intervals" not in context.params + and intervals is None ): raise ValueError( "Calibration preparation requires its effective interval companion." @@ -568,11 +610,7 @@ def run(self, context: KernelContext) -> KernelResult: document, candidate, references_sha256=digest, - interval_document=( - canonical_document_param(context, self.ref, "intervals") - if "intervals" in context.params - else None - ), + interval_document=intervals, ) elif any( row.get("metadata", {}).get("reference_profiles_resolved") @@ -581,7 +619,13 @@ def run(self, context: KernelContext) -> KernelResult: raise ValueError( "Profile-resolved preparation requires a reference resolution receipt." ) - tables = prepare_calibration_columns(context.tables, bindings) + if intervals is not None and resolution is None: + raise ValueError( + "An interval companion requires its reference resolution receipt." + ) + tables = prepare_calibration_columns( + context.tables, bindings, intervals=intervals + ) inventory = { (row["entity"], row["name"]) for row in (*bindings["columns"], *bindings.get("roster_counts", ())) @@ -619,6 +663,10 @@ def run(self, context: KernelContext) -> KernelResult: for entity, name in sorted(inventory) ], } + interval_inputs = _interval_input_evidence(context, bindings, intervals) + if interval_inputs: + evidence["effective_intervals"] = intervals + evidence["interval_inputs"] = interval_inputs payload = canonical_json(evidence) return KernelResult( columns=columns, @@ -627,13 +675,77 @@ def run(self, context: KernelContext) -> KernelResult: ) +def _interval_tables(bindings: Mapping, intervals: Mapping | None) -> list: + """The validated tables named by a binding's interval outputs, in order.""" + named = [] + for row in bindings.get("columns", ()): + if isinstance(row, Mapping) and "interval" in row: + if not isinstance(row["interval"], Mapping): + raise ValueError("An interval output names its table and band.") + table = row["interval"].get("table") + if table not in named: + named.append(table) + if not named: + return [] + if intervals is None: + raise ValueError( + "Interval outputs require their effective interval evidence; it is missing." + ) + tables = reference_intervals_module.validate_interval_document(intervals) + if set(named) - set(tables): + raise ValueError("Interval outputs name an undeclared interval table.") + return [tables[name] for name in named] + + +def _interval_input_rows(context: KernelContext, tables: Sequence) -> list[dict]: + rows = [] + for table in tables: + data = context.tables.get(table.entity) + if data is None or any( + column not in data + for column in ( + f"{table.entity}_id", + table.income_column, + table.universe_column, + ) + ): + raise ValueError( + f"Interval evidence for {table.id!r} is missing its " + f"{table.entity} income, universe or identity column." + ) + fingerprint = reference_intervals_module.interval_input_fingerprint + rows.append( + { + "table": table.id, + "entity": table.entity, + "income_column": table.income_column, + "universe_column": table.universe_column, + "rows": len(data), + "entity_ids_sha256": sha256_text( + canonical_json(data[f"{table.entity}_id"].tolist()) + ), + "income_values_sha256": fingerprint(data[table.income_column].tolist()), + "universe_values_sha256": fingerprint( + data[table.universe_column].tolist() + ), + } + ) + return rows + + +def _interval_input_evidence( + context: KernelContext, bindings: Mapping, intervals: Mapping | None +) -> list[dict]: + return _interval_input_rows(context, _interval_tables(bindings, intervals)) + + def _preparation_binding( context: KernelContext, surface: TargetSurface -) -> dict[str, object]: +) -> tuple[dict[str, object], list]: resolution = surface.reference_resolution artifact = context.artifacts.get("preparation") if resolution is None and artifact is None: - return {} + return {}, [] if artifact is None or artifact.type != CALIBRATION_PREPARATION_TYPE: raise ValueError( "Resolved targets require a typed calibration preparation artifact." @@ -687,11 +799,51 @@ def _preparation_binding( raise ValueError( "Calibration preparation inventory differs from the problem population." ) + intervals = evidence.get("effective_intervals") + if intervals is not None and sha256_text(canonical_json(intervals)) != evidence.get( + "effective_intervals_sha256" + ): + raise ValueError("Calibration preparation interval evidence hash mismatch.") + tables = _interval_tables(bindings, intervals) + if (intervals is None) != (not tables) or evidence.get( + "interval_inputs", [] + ) != _interval_input_rows(context, tables): + raise ValueError( + "Calibration preparation interval inputs differ from the problem population." + ) return { "reference_resolution": resolution, "preparation_sha256": sha256_text(artifact.payload), "preparation_artifact_key": artifact.key, **expected, + }, tables + + +def _interval_diagnostics( + frame: Frame, tables: Sequence, entities: Sequence[str], intervals_sha256 +) -> dict[str, object]: + """Fixed-weight boundary diagnostics; no reference value or target changes.""" + if not tables: + return {} + reports = [] + for table in tables: + if table.entity not in entities: + raise ValueError( + f"Interval diagnostics for {table.id!r} are missing evidence: the " + f"problem frame has no {table.entity!r} entity." + ) + reports.append( + reference_intervals_module.frame_boundary_diagnostics(table, frame) + ) + report = { + "schema_version": 1, + "kind": "interval_boundary_diagnostics_report", + "effective_intervals_sha256": intervals_sha256, + "tables": reports, + } + return { + "interval_diagnostics": report, + "interval_diagnostics_sha256": sha256_text(canonical_json(report)), } @@ -762,6 +914,7 @@ def implementation_hash(self) -> str: registry_module, hierarchy_module, calibrate_artifacts_module, + reference_intervals_module, *_MATRIX_MODULES, dependencies=self.capabilities.dependencies, ) @@ -778,10 +931,16 @@ def run(self, context: KernelContext) -> KernelResult: "under the alias 'surface'." ) surface = decode_target_surface(value.payload) - preparation = _preparation_binding(context, surface) + preparation, interval_tables = _preparation_binding(context, surface) frame = context_frame( context, self.ref, entities=entities, weight_entity=weight_entity ) + diagnostics = _interval_diagnostics( + frame, + interval_tables, + entities, + preparation.get("effective_intervals_sha256"), + ) problem = _compiled_problem(frame, surface.registry, weight_entity, self.ref) target_metadata = [ { @@ -808,6 +967,7 @@ def run(self, context: KernelContext) -> KernelResult: "entities": list(entities), "weight_entity": weight_entity, **preparation, + **diagnostics, }, ) return KernelResult( @@ -820,6 +980,7 @@ def run(self, context: KernelContext) -> KernelResult: "n_records": int(problem.n_weights), "weight_kind": problem.initial_weights.kind.value, **preparation, + **diagnostics, }, ) diff --git a/packages/microcosm-build/src/microcosm/build/uk_runtime/target_compile_modules.py b/packages/microcosm-build/src/microcosm/build/uk_runtime/target_compile_modules.py index 58ba918311..642a1e912a 100644 --- a/packages/microcosm-build/src/microcosm/build/uk_runtime/target_compile_modules.py +++ b/packages/microcosm-build/src/microcosm/build/uk_runtime/target_compile_modules.py @@ -23,6 +23,7 @@ UK_TARGET_COMPILE_MODULE_NAMES: tuple[str, ...] = ( "microcosm.build.cross_grain", + "microcosm.build.ledger_artifact", "microcosm.build.ledger_targets", "microcosm.build.target_materialization", "microcosm.build.target_reference_authoring", @@ -66,8 +67,10 @@ "refuses an undeclared condition and never moves a value" ), "microcosm.build.chronicle_epoch": ( - "the feed-pin epoch arithmetic chronicle_feed checks; the pinned " - "facts themselves are node inputs hashed by content" + "the feed-pin epoch arithmetic chronicle_feed checks, and the " + "consumer schema gate and epoch labels ledger_artifact applies; " + "none moves a fact value, and the pinned facts themselves are node " + "inputs hashed by content" ), "microcosm.build.gates": ( "imported for the GateResult and TargetCoverageRequirement types only" diff --git a/packages/microcosm-build/tests/engine_free/shared/test_calibration_columns.py b/packages/microcosm-build/tests/engine_free/shared/test_calibration_columns.py index c3eda2039d..2c7c73cd21 100644 --- a/packages/microcosm-build/tests/engine_free/shared/test_calibration_columns.py +++ b/packages/microcosm-build/tests/engine_free/shared/test_calibration_columns.py @@ -18,6 +18,10 @@ from microcosm.calibrate.matrix import build_constraint_matrix from microcosm.frame import EntitySchema, Frame, WeightKind, Weights from microcosm.frame.concepts import TENURE_DOMAIN +from test_support.microcosm_build.reference_intervals import ( + interval_bindings, + interval_table_fixture, +) from test_support.paths import paths_for @@ -182,10 +186,15 @@ def test_receipt_age_indicators_retain_the_published_strata_boundaries(): def test_all_active_calibration_bindings_enter_the_small_frame_matrix(): frame = _frame(prepare_calibration_columns(_tables(), _bindings())) root = paths_for("microcosm-build").package / "src/microcosm/build/nz" + profiles = json.loads((root / "reference_profiles.json").read_text()) effective, _, _ = resolve_reference_profiles( json.loads((root / "target_references.json").read_text()), - json.loads((root / "reference_profiles.json").read_text()), + profiles, {}, + json.loads((root / profiles["interval_resource"]).read_text()), + factor_context=json.loads( + (root / profiles["factor_context_resource"]).read_text() + ), ) references = [ ref @@ -336,3 +345,192 @@ def test_malformed_preparation_contracts_refuse(defect): bindings["columns"][0]["constant"] = float("nan") with pytest.raises(ValueError): prepare_calibration_columns(_tables(), bindings) + + +# --------------------------------------------------------------------------- +# Interval outputs: their own binding kind beside the predicate outputs +# --------------------------------------------------------------------------- + + +def _interval_contract(entity="person"): + table = interval_table_fixture(entity=entity, source_period=2002) + bindings = interval_bindings(table) + bindings["columns"].append({"entity": entity, "name": "counted", "constant": 1}) + return {"schema_version": 1, "tables": [table]}, bindings + + +def _interval_tables(amounts, statuses, entity="person"): + return { + entity: pd.DataFrame( + { + f"{entity}_id": range(len(amounts)), + "toy_income_cents": amounts, + "toy_income_universe": statuses, + } + ) + } + + +def test_interval_outputs_follow_the_universe_and_recompute_stale_values(): + intervals, bindings = _interval_contract() + tables = _interval_tables( + [-50, 0, 0, 100_000, 100_001, 5_000_000], + ["included", "included", "excluded", "included", "included", "excluded"], + ) + tables["person"]["toy_income_band_nil"] = [True] * 6 + prepared = prepare_calibration_columns(tables, bindings, intervals=intervals) + person = prepared["person"] + # A nonfiler with no income is excluded: never an all-person nil indicator. + assert person["toy_income_band_nil"].tolist() == [ + True, + True, + False, + False, + False, + False, + ] + assert person["toy_income_band_b0"].tolist() == [ + False, + False, + False, + True, + False, + False, + ] + assert person["toy_income_band_b1"].tolist() == [False] * 4 + [True, False] + assert person["toy_income_band_b2"].tolist() == [False] * 6 + assert person["toy_income_band_b0"].dtype == bool + assert person["counted"].tolist() == [1] * 6 + assert tables["person"]["toy_income_band_nil"].tolist() == [True] * 6 + tables["person"].loc[3, "toy_income_cents"] = 100_001 + fresh = prepare_calibration_columns(tables, bindings, intervals=intervals) + assert fresh["person"].loc[3, "toy_income_band_b1"] + assert not fresh["person"].loc[3, "toy_income_band_b0"] + + +@pytest.mark.parametrize( + ("amount", "status"), + [ + (10, "unresolved"), + (10, "unknown"), + (True, "included"), + (10.0, "included"), + ("10", "included"), + (pd.NA, "included"), + ], +) +def test_unresolved_universe_or_invalid_amount_refuses_before_any_output( + amount, status +): + intervals, bindings = _interval_contract() + tables = _interval_tables(pd.array([5, amount], dtype=object), ["included", status]) + before = copy.deepcopy(tables) + with pytest.raises(ValueError, match="refused before emitting indicators"): + prepare_calibration_columns(tables, bindings, intervals=intervals) + pd.testing.assert_frame_equal(tables["person"], before["person"]) + + +def test_household_entity_interval_outputs_are_entity_generic(): + intervals, bindings = _interval_contract(entity="household") + prepared = prepare_calibration_columns( + _interval_tables([0, 100_000], ["excluded", "included"], entity="household"), + bindings, + intervals=intervals, + ) + assert prepared["household"]["toy_income_band_b0"].tolist() == [False, True] + assert prepared["household"]["toy_income_band_nil"].tolist() == [False, False] + + +@pytest.mark.parametrize( + "defect", + [ + "no_document", + "unknown_table", + "unknown_band", + "wrong_entity", + "not_the_band_indicator", + "mixed_with_predicates", + "mixed_with_constant", + "extra_interval_field", + "unaged_source_cuts", + "missing_universe_column", + "missing_income_column", + "invalid_document", + ], +) +def test_malformed_interval_outputs_refuse(defect): + intervals, bindings = _interval_contract() + entry = bindings["columns"][1] + tables = _interval_tables([1, 2], ["included", "included"]) + if defect == "no_document": + intervals = None + elif defect == "unknown_table": + entry["interval"]["table"] = "other" + elif defect == "unknown_band": + entry["interval"]["band"] = "b9" + elif defect == "wrong_entity": + bindings["required_inputs"]["household"] = ["household_id"] + bindings["input_domains"]["household"] = {"household_id": {"kind": "identity"}} + tables["household"] = pd.DataFrame({"household_id": [0]}) + entry["entity"] = "household" + elif defect == "not_the_band_indicator": + entry["name"] = "renamed_indicator" + elif defect == "mixed_with_predicates": + entry["predicates"] = [{"column": "person_id", "operator": "ge", "value": 0}] + elif defect == "mixed_with_constant": + entry["constant"] = 1 + elif defect == "extra_interval_field": + entry["interval"]["closure"] = "left" + elif defect == "unaged_source_cuts": + intervals["tables"][0]["source_period"] = 2001 + elif defect == "missing_universe_column": + tables["person"] = tables["person"].drop(columns="toy_income_universe") + elif defect == "missing_income_column": + tables["person"] = tables["person"].drop(columns="toy_income_cents") + else: + intervals["tables"][0].pop("positive_band_closure") + with pytest.raises(ValueError): + prepare_calibration_columns(tables, bindings, intervals=intervals) + + +def test_interval_outputs_enter_a_constraint_row_through_their_filter(): + intervals, bindings = _interval_contract() + tables = _interval_tables([0, 50_000, 150_000], ["included"] * 3) + tables["household"] = pd.DataFrame({"household_id": [0, 1, 2]}) + tables["person"]["person_household_id"] = [0, 1, 2] + prepared = prepare_calibration_columns(tables, bindings, intervals=intervals) + frame = _frame(prepared) + target = Target( + name="first band", + entity="person", + measure="toy_income_cents", + filter="toy_income_band_b0", + ) + assert target.constraint_row(frame).tolist() == [0, 50_000, 0] + + +def test_signed_integer_domain_admits_losses_and_refuses_booleans_and_floats(): + bindings = { + "schema_version": 1, + "required_inputs": {"person": ["person_id", "net_cents"]}, + "input_domains": { + "person": { + "person_id": {"kind": "identity"}, + "net_cents": {"kind": "signed_integer"}, + } + }, + "columns": [ + { + "entity": "person", + "name": "loss_indicator", + "predicates": [{"column": "net_cents", "operator": "lt", "value": 0}], + } + ], + } + tables = {"person": pd.DataFrame({"person_id": [0, 1], "net_cents": [-5, 7]})} + prepared = prepare_calibration_columns(tables, bindings) + assert prepared["person"]["loss_indicator"].tolist() == [True, False] + for values in ([True, False], [-5.0, 7.0], pd.array([-5, None], dtype="Int64")): + tables["person"]["net_cents"] = values + with pytest.raises(ValueError): + prepare_calibration_columns(tables, bindings) diff --git a/packages/microcosm-build/tests/engine_free/shared/test_ledger_artifact.py b/packages/microcosm-build/tests/engine_free/shared/test_ledger_artifact.py index 1307e09d06..7dc217711d 100644 --- a/packages/microcosm-build/tests/engine_free/shared/test_ledger_artifact.py +++ b/packages/microcosm-build/tests/engine_free/shared/test_ledger_artifact.py @@ -2,11 +2,14 @@ from __future__ import annotations +import ast import hashlib import json import os +import pickle import runpy from argparse import ArgumentParser, Namespace +from copy import deepcopy from dataclasses import replace from pathlib import Path @@ -18,11 +21,13 @@ CONSUMER_ARTIFACT_SCHEMA_VERSION, ChronicleFeedPinMismatchError, LedgerConsumerArtifact, + LexicalFloat, add_ledger_artifact_args, load_ledger_consumer_artifact, resolve_ledger_artifact, validate_chronicle_feed_pin, ) +from microcosm.graph.canonical import canonical_json from test_support.microcosm_build.chronicle_feed import write_pinned_artifact from test_support.paths import paths_for @@ -87,6 +92,109 @@ def test_loads_bare_consumer_facts_file(tmp_path): assert provenance["schema_version"] is None +def test_authenticated_float_retains_lexical_token_without_changing_json(tmp_path): + facts_path = tmp_path / "consumer_facts.jsonl" + original = '{"aggregate_fact_key":"decimal","value":1.2500e2}\n' + facts_path.write_text(original) + facts_sha = hashlib.sha256(original.encode()).hexdigest() + artifact = load_ledger_consumer_artifact( + facts_path, expected_facts_sha256=facts_sha, lexical_floats=True + ) + value = artifact.facts[0]["value"] + assert isinstance(value, LexicalFloat) + assert not hasattr(value, "__dict__") + assert value.lexical_token == "1.2500e2" + assert value == 125.0 + assert hash(value) == hash(125.0) + assert json.dumps(value).encode() == json.dumps(125.0).encode() + assert json.dumps(artifact.facts[0], sort_keys=True) == json.dumps( + json.loads(original), sort_keys=True + ) + assert artifact.facts_sha256 == facts_sha + + +@pytest.mark.parametrize("pinned", [False, True]) +def test_default_float_loading_returns_exact_builtin_float(tmp_path, pinned): + path, pin = write_pinned_artifact(tmp_path / "artifact", [_fact_row(value=0.1)]) + artifact = load_ledger_consumer_artifact( + path, **({"feed_pin": pin} if pinned else {}) + ) + + assert type(artifact.facts[0]["value"]) is float + + +def test_lexical_float_opt_in_is_limited_to_factor_consumers(): + repository = paths_for("microcosm-build").repository + sources = list((repository / "packages").glob("*/src/**/*.py")) + sources.extend((repository / "tools").rglob("*.py")) + opt_ins = set() + for path in sources: + for node in ast.walk(ast.parse(path.read_text())): + if not isinstance(node, ast.Call): + continue + for keyword in node.keywords: + if keyword.arg != "lexical_floats": + continue + # A loader forwarding its caller's choice is not an opt-in. + if ( + isinstance(keyword.value, ast.Name) + and keyword.value.id == "lexical_floats" + ): + continue + if ( + isinstance(keyword.value, ast.Constant) + and keyword.value.value is False + ): + continue + opt_ins.add(path.relative_to(repository).as_posix()) + assert opt_ins == { + "packages/microcosm-build/src/microcosm/build/transport/target_kernels.py", + "tools/generate_nz_reference_aging.py", + } + + +@pytest.mark.parametrize("protocol", range(pickle.HIGHEST_PROTOCOL + 1)) +def test_authenticated_float_pickle_preserves_lexical_token(tmp_path, protocol): + facts_path = tmp_path / "consumer_facts.jsonl" + facts_path.write_text('{"aggregate_fact_key":"decimal","value":1.2500e2}\n') + value = load_ledger_consumer_artifact(facts_path, lexical_floats=True).facts[0][ + "value" + ] + + restored = pickle.loads(pickle.dumps(value, protocol=protocol)) + + assert isinstance(restored, LexicalFloat) + assert restored.lexical_token == "1.2500e2" + assert restored == value + assert not hasattr(restored, "__dict__") + + +def test_authenticated_float_deepcopy_preserves_lexical_token(tmp_path): + facts_path = tmp_path / "consumer_facts.jsonl" + facts_path.write_text('{"aggregate_fact_key":"decimal","value":1.2500e2}\n') + value = load_ledger_consumer_artifact(facts_path, lexical_floats=True).facts[0][ + "value" + ] + + restored = deepcopy(value) + + assert isinstance(restored, LexicalFloat) + assert restored.lexical_token == "1.2500e2" + assert restored == value + assert not hasattr(restored, "__dict__") + + +@pytest.mark.parametrize("token", ["125", "9007199254740993", str(10**100 + 1)]) +def test_authenticated_integer_tokens_stay_exact_integers(tmp_path, token): + facts_path = tmp_path / "consumer_facts.jsonl" + facts_path.write_text('{"aggregate_fact_key":"integer","value":' + token + "}\n") + + value = load_ledger_consumer_artifact(facts_path).facts[0]["value"] + + assert type(value) is int + assert value == int(token) + + def test_loads_artifact_directory_and_records_provenance(tmp_path): rows = [_fact_row(), _fact_row(assertion="source_projection")] artifact_dir = _write_artifact_dir(tmp_path, rows) @@ -520,3 +628,38 @@ def test_real_nz_artifact_matches_committed_feed_pin(): assert artifact.fact_row_count == pin["fact_row_count"] assert artifact.schema_version == pin["artifact_schema_version"] assert list(artifact.fact_schema_versions) == pin["consumer_fact_schema_versions"] + + +def test_real_nz_lexical_opt_in_preserves_canonical_bytes(): + artifact_path = os.environ.get("NZ_CHRONICLE_ARTIFACT") + if not artifact_path: + pytest.skip("NZ_CHRONICLE_ARTIFACT is unset") + pin_path = ( + paths_for("microcosm-build").package + / "src/microcosm/build/nz/chronicle_feed.json" + ) + pin = json.loads(pin_path.read_text()) + plain = load_ledger_consumer_artifact(artifact_path, feed_pin=pin) + lexical = load_ledger_consumer_artifact( + artifact_path, feed_pin=pin, lexical_floats=True + ) + + def floats(value): + if isinstance(value, float): + yield value + elif isinstance(value, dict): + for child in value.values(): + yield from floats(child) + elif isinstance(value, (list, tuple)): + for child in value: + yield from floats(child) + + plain_values, lexical_values = ( + list(floats(plain.facts)), + list(floats(lexical.facts)), + ) + assert plain_values + assert all(type(value) is float for value in plain_values) + assert all(type(value) is LexicalFloat for value in lexical_values) + assert [float(value.lexical_token) for value in lexical_values] == plain_values + assert canonical_json(plain.facts) == canonical_json(lexical.facts) diff --git a/packages/microcosm-build/tests/engine_free/shared/test_ledger_targets.py b/packages/microcosm-build/tests/engine_free/shared/test_ledger_targets.py index 59fe6e2246..2a9413fb65 100644 --- a/packages/microcosm-build/tests/engine_free/shared/test_ledger_targets.py +++ b/packages/microcosm-build/tests/engine_free/shared/test_ledger_targets.py @@ -7,9 +7,14 @@ TargetCoverageRequirement, target_profile_coverage_gate, ) +from microcosm.build.ledger_artifact import ( + LexicalFloat, + load_ledger_consumer_artifact, +) from microcosm.build.ledger_targets import ( LedgerTargetMapping, LedgerTargetReference, + _strict_scalar_equal, apply_ledger_target_profile, compile_ledger_target_references, constraint_bound_shadowing_dimensions, @@ -1729,6 +1734,58 @@ def test__given_selector_matches_multiple_eligible_months__then_latest_month_is_ class TestLedgerSelectorExtensions: + @pytest.mark.parametrize( + ("actual", "expected", "equal"), + [ + (LexicalFloat("0.1"), 0.1, True), + (0.1, LexicalFloat("0.1"), True), + (LexicalFloat("0.1"), LexicalFloat("0.10"), True), + (1, 1.0, False), + (1.0, 1, False), + (True, 1, False), + (1, True, False), + (True, 1.0, False), + (1.0, True, False), + (LexicalFloat("1.0"), 1, False), + (1, LexicalFloat("1.0"), False), + (LexicalFloat("1.0"), True, False), + (True, LexicalFloat("1.0"), False), + ], + ) + def test_strict_scalar_equal_treats_lexical_floats_as_floats( + self, actual, expected, equal + ) -> None: + assert _strict_scalar_equal(actual, expected) is equal + + @pytest.mark.parametrize("lexical_floats", [False, True]) + def test_float_dimension_pin_compiles_loaded_fact( + self, tmp_path, lexical_floats + ) -> None: + facts_path = tmp_path / "consumer_facts.jsonl" + facts_path.write_text( + json.dumps(_consumer_fact_row(dimensions={"band": 0.1})) + "\n" + ) + artifact = load_ledger_consumer_artifact( + facts_path, lexical_floats=lexical_floats + ) + dimension = artifact.facts[0]["dimensions"]["band"] + assert type(dimension) is (LexicalFloat if lexical_floats else float) + reference = LedgerTargetReference( + name="float dimension selector", + ledger_selector={"dimension_values": {"band": 0.1}}, + entity="tax_unit", + measure="adjusted_gross_income", + period=2023, + family="irs_soi", + ) + + (target,) = compile_ledger_target_references( + artifact.facts, [reference], country="us" + ).specs + + assert target.name == reference.name + assert target.value == artifact.facts[0]["value"] + def test_dimension_values_use_strict_typed_equality(self) -> None: reference = LedgerTargetReference( name="typed dimension selector", diff --git a/packages/microcosm-build/tests/engine_free/shared/test_nz_reference_aging.py b/packages/microcosm-build/tests/engine_free/shared/test_nz_reference_aging.py new file mode 100644 index 0000000000..fa9ecb3aca --- /dev/null +++ b/packages/microcosm-build/tests/engine_free/shared/test_nz_reference_aging.py @@ -0,0 +1,290 @@ +"""NZ feed operands, reviewed factors, and the observed-quarter re-declaration.""" + +from __future__ import annotations + +import copy +import json +import os +from datetime import date +from decimal import Decimal, localcontext +from fractions import Fraction +from pathlib import Path + +import pytest + +from microcosm.build import reference_factors +from microcosm.build.ledger_artifact import ( + LexicalFloat, + load_ledger_consumer_artifact, + validate_chronicle_feed_pin, +) +from microcosm.build.ledger_targets import fact_matches_selector +from microcosm.build.reference_factors import ( + replay_reference_factor, + require_current_factors, + resolve_reference_factor, + validate_factor_context, +) +from test_support.paths import paths_for +from tools.generate_nz_reference_aging import ( + _OPERANDS, + build_reference_aging, +) + +_PATHS = paths_for("microcosm-build") +_SPEC = _PATHS.package / "src/microcosm/build/nz" +_EXPECTED = { + "ird_ty2024_to_ty2027_low": 1115056, + "ird_ty2024_to_ty2027_central": 1117109, + "ird_ty2024_to_ty2027_high": 1119158, + "p1_ty2026_to_ty2027_low": 1026690, + "p1_ty2026_to_ty2027_central": 1028580, + "p1_ty2026_to_ty2027_high": 1030467, + "observed_ty2026_over_ty2024": 1086069, +} + + +def _document(): + return json.loads((_SPEC / "reference_aging.json").read_text()) + + +def _entry(factor_id="ird_ty2024_to_ty2027_central"): + return next( + entry + for entry in _document()["factors"] + if entry["declaration"]["id"] == factor_id + ) + + +def _fraction(rational): + return Fraction(rational["numerator"], rational["denominator"]) + + +@pytest.fixture(scope="module") +def artifact(): + root = os.environ.get("NZ_CHRONICLE_ARTIFACT") + if not root: + pytest.skip("NZ_CHRONICLE_ARTIFACT is not set") + loaded = load_ledger_consumer_artifact(Path(root), lexical_floats=True) + validate_chronicle_feed_pin(loaded, _document()["feed_identity"]) + return loaded + + +@pytest.fixture(scope="module") +def operand_facts(artifact): + keys = {f"ledger.aggregate_fact.v2:{suffix}" for _, _, suffix, _ in _OPERANDS} + keys.add("ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25") + return tuple(fact for fact in artifact.facts if fact["aggregate_fact_key"] in keys) + + +def test_generated_aging_resource_reproduces_pinned_feed_and_all_receipts(artifact): + assert build_reference_aging(artifact) == _document() + assert set(validate_factor_context(_document())) == set(_EXPECTED) + identity = _document()["feed_identity"] + assert set(identity) == { + "source_commit", + "facts_sha256", + "manifest_sha256", + "artifact_schema_version", + "consumer_fact_schema_versions", + "consumer_fact_schema_sha256", + "fact_row_count", + } + for entry in _document()["factors"]: + assert entry["declaration"]["feed_identity"] == identity + assert entry["receipt"]["feed_identity"] == identity + + +def test_packaged_factor_context_validation_ignores_the_wall_clock(monkeypatch): + class FutureDate(date): + @classmethod + def today(cls): + return cls(2026, 11, 5) + + monkeypatch.setattr(reference_factors, "date", FutureDate) + + assert set(validate_factor_context(_document())) == set(_EXPECTED) + + +@pytest.mark.parametrize( + "today,current", + [ + (date(2026, 10, 22), False), + (date(2026, 10, 23), True), + (date(2026, 11, 3), True), + (date(2026, 11, 4), False), + ], +) +def test_factor_currency_uses_inclusive_declared_boundaries(today, current): + selected = validate_factor_context(_document()) + if current: + require_current_factors(selected, today=today) + else: + with pytest.raises(ValueError, match="reviewed re-declaration") as error: + require_current_factors(selected, today=today) + for factor_id in selected: + assert factor_id in str(error.value) + + +@pytest.mark.parametrize("factor_id", list(_EXPECTED)) +def test_all_six_factors_and_observed_diagnostic_are_exact(factor_id, operand_facts): + entry = _entry(factor_id) + declaration = entry["declaration"] + expected = {"numerator": _EXPECTED[factor_id], "denominator": 1000000} + factor, receipt = resolve_reference_factor( + declaration, operand_facts, _document()["feed_identity"] + ) + assert factor == expected == declaration["expected_operational_factor"] + assert receipt == entry["receipt"] + assert receipt["operation"] == "projected_period_average_ratio" + assert receipt["operation_version"] == 1 + assert receipt["subperiods_per_year"] == 4 + assert _fraction(receipt["denominator_mean"]) == ( + Fraction("1670.0725") if factor_id.startswith("p1_") else Fraction("1537.7225") + ) + assert declaration["purpose"] == ( + "diagnostic" if factor_id.startswith("observed_") else "profile_input" + ) + replay_reference_factor( + declaration, operand_facts, _document()["feed_identity"], factor, receipt + ) + + +def test_each_reviewed_operand_resolves_once_with_exact_lexical_evidence(artifact): + for line, period, suffix, expected in _OPERANDS: + fact = artifact.facts[line - 1] + assert fact["aggregate_fact_key"] == f"ledger.aggregate_fact.v2:{suffix}" + assert fact["period"]["value"] == period + assert fact["value"].lexical_token == expected + checked = set() + for entry in _document()["factors"]: + declaration = entry["declaration"] + slots = [*declaration["source_schedule"], *declaration["target_schedule"]] + if declaration["growth"]: + slots.append(declaration["growth"]) + for slot in slots: + identity = json.dumps( + {"selector": slot["selector"], "validation": slot["validation"]}, + sort_keys=True, + ) + if identity in checked: + continue + checked.add(identity) + matches = [ + fact + for fact in artifact.facts + if fact_matches_selector(fact, slot["selector"]) + ] + if not matches: + assert slot in declaration["target_schedule"] + assert slot["projection_offset"] > 0 + continue + (fact,) = matches + validation = slot["validation"] + assert fact["observed_measure"]["unit"] == validation["unit"] + assert fact["source"]["source_sha256"] == validation["source_sha256"] + assert fact["source"]["vintage"] == validation["source_vintage"] + assert fact["entity"]["role"] == validation["entity_role"] + assert fact["assertion"] == validation["assertion"] + assert fact["provenance_class"] == validation["provenance_class"] + for key in ("start_date", "end_date"): + assert ( + fact["period_coverage"][key] == validation["period_coverage"][key] + ) + + +def test_treasury_fy2027_source_column_uses_chronicle_2026_and_2027_refuses( + operand_facts, +): + declaration = _entry()["declaration"] + assert declaration["growth"]["selector"]["period_value"] == 2026 + assert declaration["growth"]["validation"]["source_column_id"] == ( + "year_ending_30_june_2027" + ) + declaration["growth"]["selector"]["period_value"] = 2027 + with pytest.raises(ValueError, match="resolve exactly once"): + resolve_reference_factor( + declaration, operand_facts, _document()["feed_identity"] + ) + + +def test_p1_high_rounds_once_to_1030467_and_old_truncation_refuses(operand_facts): + declaration = _entry("p1_ty2026_to_ty2027_high")["declaration"] + assert declaration["source_period"] == 2026 + assert [ + row["selector"]["period_value"] for row in declaration["source_schedule"] + ] == ["2025-Q2", "2025-Q3", "2025-Q4", "2026-Q1"] + declaration["expected_operational_factor"]["numerator"] = 1030466 + with pytest.raises(ValueError, match="expected factor mismatch"): + resolve_reference_factor( + declaration, operand_facts, _document()["feed_identity"] + ) + + +def test_root_enclosure_certifies_no_rounded_quarters_and_irrational_root(): + for factor_id in list(_EXPECTED)[:6]: + entry = _entry(factor_id) + receipt = entry["receipt"] + delta = Fraction(entry["declaration"]["growth"]["scenario_delta"]) + radicand = 1 + (Fraction("2.7") + delta) / 100 + lower = _fraction(receipt["root_bounds"]["lower"]) + upper = _fraction(receipt["root_bounds"]["upper"]) + assert lower**4 < radicand < upper**4 + assert receipt["root_bounds"]["exact"] is False + denominator = _fraction(receipt["denominator_mean"]) + assert _fraction(receipt["numerator_mean_bounds"]["lower"]) == ( + Fraction("1700.68") * sum(lower**i for i in range(4)) / 4 + ) + for bound in ("lower", "upper"): + value = _fraction(receipt["unrounded_factor_bounds"][bound]) + assert ( + value + == _fraction(receipt["numerator_mean_bounds"][bound]) / denominator + ) + assert round(value * 1000000) == _EXPECTED[factor_id] + + +def test_september_observation_reanchors_and_requires_reviewed_redeclaration( + operand_facts, +): + declaration = _entry()["declaration"] + anchor = next( + fact for fact in operand_facts if fact["period"]["value"] == "2026-Q2" + ) + september = copy.deepcopy(anchor) + september["aggregate_fact_key"] = "ledger.aggregate_fact.v2:synthetic_september" + september["period"]["value"] = "2026-Q3" + september["layout"]["record_set_id"] = "stats_nz.qes.awe.2026q3" + september["period_coverage"].update( + {"start_date": "2026-07-01", "end_date": "2026-09-30"} + ) + september["value"] = LexicalFloat("1750.00") + declaration["feed_identity"]["facts_sha256"] = "9" * 64 + facts = (*operand_facts, september) + with pytest.raises(ValueError, match="expected factor mismatch.*re-declaration"): + resolve_reference_factor(declaration, facts, declaration["feed_identity"]) + with localcontext() as context: + context.prec = 80 + q = (Decimal("1.027").sqrt()).sqrt() + numerator = (Decimal("1700.68") + Decimal(1750) * (1 + q + q * q)) / 4 + expected = round(numerator / Decimal("1537.7225") * 1000000) + declaration["expected_operational_factor"]["numerator"] = expected + factor, receipt = resolve_reference_factor( + declaration, facts, declaration["feed_identity"] + ) + assert factor["numerator"] == expected + assert [slot["status"] for slot in receipt["target_schedule"]] == [ + "observed", + "observed", + "projected", + "projected", + ] + lower = _fraction(receipt["root_bounds"]["lower"]) + assert ( + _fraction(receipt["numerator_mean_bounds"]["lower"]) + == (Fraction("1700.68") + 1750 * (1 + lower + lower**2)) / 4 + ) + for slot in receipt["target_schedule"][2:]: + assert slot["projection_anchor"] == { + "aggregate_fact_key": september["aggregate_fact_key"] + } diff --git a/packages/microcosm-build/tests/engine_free/shared/test_nz_reference_intervals.py b/packages/microcosm-build/tests/engine_free/shared/test_nz_reference_intervals.py new file mode 100644 index 0000000000..02908e1510 --- /dev/null +++ b/packages/microcosm-build/tests/engine_free/shared/test_nz_reference_intervals.py @@ -0,0 +1,340 @@ +"""NZ IRD interval declarations: generated cuts, companions and the declared convention. + +The row formulas below are NZ data, checked here against the packaged +resource; the shared interval module contains none of them. +""" + +from __future__ import annotations + +import json +import os +from fractions import Fraction +from pathlib import Path + +import pytest + +from microcosm.build.ledger_artifact import load_ledger_consumer_artifact +from microcosm.build.reference_intervals import ( + classify_records, + interval_table, + validate_interval_document, +) +from microcosm.build.reference_profiles import resolve_reference_profiles +from test_support.paths import paths_for + +_SPEC = paths_for("microcosm-build").package / "src/microcosm/build/nz" +_REPOSITORY = paths_for("microcosm-build").repository +NATIONAL = "ird_taxable_income_national_ty2024" +AGE = "ird_taxable_income_age_ty2024" +IRD_REASON = ( + "B4: reviewed IRD-definition taxable-income measurement, annual component " + "closure and record universe remain required. Ageing resolution does not " + "establish that measurement." +) + + +def _document(name): + return json.loads((_SPEC / name).read_text()) + + +def _national_upper(row): + if row == 9: + return 100 + if row == 10: + return 1_000 + if row <= 209: + return 1_000 * (row - 9) + if row <= 229: + return 200_000 + 5_000 * (row - 209) + if row <= 243: + return 300_000 + 50_000 * (row - 229) + return None + + +def _age_upper(row): + if row == 7: + return 100 + if row == 8: + return 1_000 + if row <= 187: + return 1_000 * (row - 7) + return None + + +def _tables(): + return { + table["id"]: table for table in _document("reference_intervals.json")["tables"] + } + + +def _upper_dollars(band): + return None if band["upper_cent"] is None else band["upper_cent"] / 100 + + +def test_document_validates_under_the_shared_contract_with_declared_semantics(): + parsed = validate_interval_document(_document("reference_intervals.json")) + assert list(parsed) == [NATIONAL, AGE] + for table in _tables().values(): + assert { + key: table[key] + for key in ( + "entity", + "currency", + "input_unit", + "income_column", + "universe_column", + "source_period", + "target_period", + "positive_band_closure", + "nil_band", + "negative_income_policy", + "first_lower_cut_cents", + "diagnostics", + ) + } == { + "entity": "person", + "currency": "NZD", + "input_unit": "integer_cent", + "income_column": "ird_taxable_income_proxy_cents", + "universe_column": "ird_taxable_income_proxy_universe_status", + "source_period": 2024, + "target_period": 2027, + "positive_band_closure": "right", + "nil_band": "present", + "negative_income_policy": "floor_zero", + "first_lower_cut_cents": 0, + "diagnostics": { + "boundary_window_cents": 100, + "alternative_positive_band_closure": "left", + }, + } + assert "scaling" not in table + + +def test_national_table_has_237_count_money_interval_triples_and_no_total_row(): + table = _tables()[NATIONAL] + assert table["source_locator"] == "Income tables 2001-24!BE8:BE244" + bands = table["bands"] + assert [band["id"] for band in bands] == [f"row_{row}" for row in range(8, 245)] + assert not any("246" in json.dumps(band) for band in bands) + assert bands[0] == { + "id": "row_8", + "kind": "nil", + "indicator": "taxable_income_band_row_8_indicator", + "source_label": "nil", + "count_reference": "ird_taxable_income_people_by_band__row_8", + "amount_reference": "ird_taxable_income_total_by_band__row_8", + } + for band in bands[1:]: + row = int(band["id"].removeprefix("row_")) + assert band["kind"] == "positive" + assert _upper_dollars(band) == _national_upper(row) + assert bands[-1]["source_label"] == "Over $1,000,000" + references = { + row["name"]: row + for row in _document("target_references.json")["target_references"] + } + profiles = _document("reference_profiles.json") + for profile in ("low", "central", "high"): + (transformation,) = profiles["dimensions"]["aging_index"]["profiles"][profile][ + "transformations" + ] + assert transformation["interval_table_ids"] == [NATIONAL] + assert transformation["count_reference_names"] == [ + band["count_reference"] for band in bands + ] + assert transformation["reference_names"] == [ + band["amount_reference"] for band in bands + ] + for band in bands: + for name in (band["count_reference"], band["amount_reference"]): + assert references[name]["filter"] == band["indicator"] + assert references[name]["entity"] == "person" + + +def test_age_table_has_183_bands_and_no_companions_or_fit_rows(): + table = _tables()[AGE] + assert table["source_locator"] == "A6:A188" + bands = table["bands"] + assert [band["id"] for band in bands] == [f"row_{row}" for row in range(6, 189)] + assert bands[0]["kind"] == "nil" + for band in bands[1:]: + assert _upper_dollars(band) == _age_upper(int(band["id"].removeprefix("row_"))) + assert bands[-1]["source_label"] == "Over $180,000" + assert all( + "count_reference" not in band and "amount_reference" not in band + for band in bands + ) + indicators = {band["indicator"] for band in bands} + for name in ("target_references.json", "precal_references.json"): + assert not any( + row.get("filter") in indicators + for row in _document(name)["target_references"] + ) + profiles = json.dumps(_document("reference_profiles.json")) + assert AGE not in profiles + + +@pytest.mark.parametrize( + ("table", "rows", "endpoint"), + [ + (NATIONAL, (29, 30), 20_000), + (NATIONAL, (59, 60), 50_000), + (NATIONAL, (89, 90), 80_000), + (NATIONAL, (229, 230), 300_000), + (AGE, (27, 28), 20_000), + (AGE, (57, 58), 50_000), + (AGE, (87, 88), 80_000), + ], +) +def test_shared_endpoint_labels_resolve_to_the_ordered_cuts(table, rows, endpoint): + declaration = _tables()[table] + by_id = {band["id"]: band for band in declaration["bands"]} + lower, upper = (by_id[f"row_{row}"] for row in rows) + label = f"${endpoint:,}" + # Both published labels name the endpoint; the ordered cut gives it to the + # lower band under the declared right-closed convention. + assert lower["source_label"].replace(" ", "").endswith(label) + assert upper["source_label"].replace(" ", "").startswith(label) + assert lower["upper_cent"] == endpoint * 100 + parsed = interval_table(declaration) + positions = classify_records( + parsed, + [endpoint * 100 - 1, endpoint * 100, endpoint * 100 + 1], + ["included"] * 3, + ) + assert [parsed.band_ids[index] for index in positions] == [ + lower["id"], + lower["id"], + upper["id"], + ] + + +def test_central_ageing_keeps_fractional_cent_cuts_exactly(): + _, intervals, receipt = resolve_reference_profiles( + _document("target_references.json"), + _document("reference_profiles.json"), + {}, + _document("reference_intervals.json"), + factor_context=_document("reference_aging.json"), + ) + tables = {table["id"]: table for table in intervals["tables"]} + national = tables[NATIONAL] + by_id = {band["id"]: band for band in national["bands"]} + cuts = { + row: Fraction( + by_id[f"row_{row}"]["upper_cent"]["numerator"], + by_id[f"row_{row}"]["upper_cent"]["denominator"], + ) + for row in (9, 10, 49) + } + # $100, $1,000 and $40,000 at the central factor 1.117109. + assert cuts == { + 9: Fraction("11171.09"), + 10: Fraction("111710.9"), + 49: Fraction(4_468_436), + } + parsed = interval_table(national) + positions = classify_records( + parsed, [11_171, 11_172, 111_710, 111_711], ["included"] * 4 + ) + assert [parsed.band_ids[index] for index in positions] == [ + "row_9", + "row_10", + "row_10", + "row_11", + ] + assert tables[AGE] == _tables()[AGE] + assert receipt["interval_tables"][NATIONAL]["factor_id"] == ( + "ird_ty2024_to_ty2027_central" + ) + + +def test_resolution_is_not_activation_and_no_active_row_requests_the_proxy(): + intervals = _document("reference_intervals.json") + proxy = { + "ird_taxable_income_proxy_cents", + "ird_taxable_income_proxy_universe_status", + } + indicators = { + band["indicator"] for table in intervals["tables"] for band in table["bands"] + } + for profile in ("low", "central", "high"): + effective, _, _ = resolve_reference_profiles( + _document("target_references.json"), + _document("reference_profiles.json"), + {"aging_index": profile}, + intervals, + factor_context=_document("reference_aging.json"), + ) + ird = [ + row + for row in effective["target_references"] + if row["name"].startswith("ird_taxable_income_") + ] + assert len(ird) == 474 + assert all( + row["metadata"]["activation_status"] == "requires_prerequisites" + and row["metadata"]["parking_reason"] == IRD_REASON + for row in ird + ) + for row in effective["target_references"]: + if row["metadata"].get("activation_status", "active") == "active": + assert row.get("filter") not in indicators + assert row.get("measure") not in proxy + bindings = json.dumps(_document("calibration_bindings.json")) + assert not any(name in bindings for name in proxy | indicators) + precal = _document("precal_references.json")["target_references"] + wages = [row for row in precal if row["name"].startswith("ird_wage_salary_")] + assert len(wages) == 235 + assert all( + row["metadata"]["activation_status"] + == "requires_g8r2_source_period_wage_bridge_and_intervals" + for row in wages + ) + + +def test_declared_convention_is_disclosed_in_the_resource_and_the_docs(): + disclosure = _document("reference_intervals.json")["disclosure"] + for phrase in ( + "IRD publishes no band closure or cents semantics", + "Microcosm's declared", + "convention", + "publisher reclassification is unavailable", + ): + assert phrase in disclosure + docs = (_REPOSITORY / "docs/nz-calibration-targets.md").read_text() + assert "IRD publishes no band closure or cents semantics" in docs + assert "declared convention" in docs + + +@pytest.fixture(scope="module") +def artifact(): + path = os.environ.get("NZ_CHRONICLE_ARTIFACT") + if not path: + pytest.skip("NZ_CHRONICLE_ARTIFACT is unset; public NZ feed audit unavailable") + return load_ledger_consumer_artifact( + Path(path), feed_pin=_document("chronicle_feed.json") + ) + + +def test_every_band_label_is_the_feed_label_for_its_row(artifact): + record_sets = { + NATIONAL: "ird_taxable_income_distribution.ty2024.income_bands", + AGE: "ird_taxable_income_distribution.ty2024.age_by_income_band", + } + for table_id, record_set in record_sets.items(): + labels = {} + for fact in artifact.facts: + layout = fact.get("layout", {}) + if ( + layout.get("record_set_id") == record_set + and layout.get("table_record_kind") == "detail" + ): + labels.setdefault(layout["source_row_id"], set()).add( + fact["dimensions"]["taxable_income_band_source_label"] + ) + bands = _tables()[table_id]["bands"] + assert set(labels) == {band["id"] for band in bands} + for band in bands: + assert labels[band["id"]] == {band["source_label"]} diff --git a/packages/microcosm-build/tests/engine_free/shared/test_nz_spec_package.py b/packages/microcosm-build/tests/engine_free/shared/test_nz_spec_package.py index 7e9fba0e58..6a30848d75 100644 --- a/packages/microcosm-build/tests/engine_free/shared/test_nz_spec_package.py +++ b/packages/microcosm-build/tests/engine_free/shared/test_nz_spec_package.py @@ -158,7 +158,11 @@ from hypothesis import assume, given, settings from hypothesis import strategies as st +from microcosm.build.chronicle_epoch import ( + is_accepted_consumer_artifact_schema_version, +) from microcosm.build.country_spec import load_country_spec +from microcosm.build.ledger_artifact import chronicle_feed_identity from microcosm.build.ledger_targets import ( LedgerTargetReference, compile_ledger_target_references, @@ -305,8 +309,9 @@ def rulespec_commit_mentions(value: object) -> set[str]: "rulespec" in any case); - the value, at any depth, of a key that contains "commit" in any case, unless the key's mapping is a foreign record (its repository - attribution lacks "rulespec") and neither the key nor an enclosing - key contains "rulespec". + attribution lacks "rulespec") or the key is one of the seven fields + of a complete Chronicle identity below ``feed_identity``, and neither + the key nor an enclosing key contains "rulespec". A foreign record cancels the context it sits in, except that its commit keys still count below a rulespec key. Integers count where hex strings @@ -316,7 +321,13 @@ def rulespec_commit_mentions(value: object) -> set[str]: found: set[str] = set() - def visit(node: object, *, rulespec_context: bool, commit_value: bool) -> None: + def visit( + node: object, + *, + rulespec_context: bool, + commit_value: bool, + feed_identity_record: bool = False, + ) -> None: if isinstance(node, Mapping): repositories = [ repository @@ -327,6 +338,14 @@ def visit(node: object, *, rulespec_context: bool, commit_value: bool) -> None: rulespec_record = any( "rulespec" in repository.lower() for repository in repositories ) + artifact_identity_fields: set[str] = set() + if feed_identity_record and is_accepted_consumer_artifact_schema_version( + node.get("artifact_schema_version") + ): + try: + artifact_identity_fields = set(chronicle_feed_identity(node)) + except ValueError: + pass foreign = named and not rulespec_record if rulespec_record: commit_value = True @@ -334,16 +353,23 @@ def visit(node: object, *, rulespec_context: bool, commit_value: bool) -> None: commit_value = False for key, child in node.items(): name = str(key).lower() - commit_key = "commit" in name and (rulespec_context or not foreign) + identity_field = key in artifact_identity_fields + field_commit_value = commit_value and ( + rulespec_context or not identity_field + ) + commit_key = "commit" in name and ( + rulespec_context or (not foreign and not identity_field) + ) visit( str(key), rulespec_context=rulespec_context, - commit_value=commit_value, + commit_value=field_commit_value, ) visit( child, rulespec_context=rulespec_context or "rulespec" in name, - commit_value=commit_value or commit_key or "rulespec" in name, + commit_value=field_commit_value or commit_key or "rulespec" in name, + feed_identity_record=name == "feed_identity", ) elif isinstance(node, list): for child in node: @@ -1193,7 +1219,12 @@ def test_each_set_is_a_self_identifying_nz_reference_resource( assert document["country"] == "nz" assert document["reference_set"] == reference_set expected_operations = ( - ["identity", "rolled_forward_by_ratio", "allocated_residual_by_ratio"] + [ + "identity", + "rolled_forward_by_ratio", + "allocated_residual_by_ratio", + "linear_combination", + ] if reference_set == "calibration" else ["identity"] ) @@ -1452,6 +1483,52 @@ def test_gate_profile_requires_exactly_the_calibration_families(self) -> None: class TestRulespecPin: + @pytest.mark.parametrize( + "case", + [ + "canonical", + "unattributed", + "incomplete", + "explicit_commit", + "extra_commit", + "rulespec_extra_revision", + "prose", + "rulespec_context", + "wrong_schema", + ], + ) + def test_chronicle_identity_scope_preserves_rulespec_mentions(self, case) -> None: + identity = _load("reference_aging.json")["feed_identity"] + commit = identity["source_commit"] + payload = {"feed_identity": identity} + expected = set() + if case == "unattributed": + payload = {"other": identity} + expected = {commit} + elif case == "incomplete": + identity.pop("manifest_sha256") + expected = {commit} + elif case == "explicit_commit": + identity["rulespec_nz_commit"] = "c0ffee1" + expected = {"c0ffee1"} + elif case == "extra_commit": + identity["commit"] = "deadbee" + expected = {"deadbee"} + elif case == "rulespec_extra_revision": + identity["revision"] = "deadbee" + payload = {"rulespec": payload} + expected = {commit, "deadbee"} + elif case == "prose": + identity["notes"] = "RuleSpec-nz deadbee" + expected = {"deadbee"} + elif case == "rulespec_context": + payload = {"rulespec": payload} + expected = {commit} + elif case == "wrong_schema": + identity["artifact_schema_version"] = "unknown" + expected = {commit} + assert rulespec_commit_mentions(payload) == expected + def test_every_rulespec_commit_named_anywhere_was_reviewed_on_main(self) -> None: pin = _load("axiom_rules_bindings.json")["rulespec"] mentions = rulespec_commit_mentions(_package_payloads()) diff --git a/packages/microcosm-build/tests/engine_free/shared/test_nz_target_references.py b/packages/microcosm-build/tests/engine_free/shared/test_nz_target_references.py index 004785b9e9..0a9d1f53a9 100644 --- a/packages/microcosm-build/tests/engine_free/shared/test_nz_target_references.py +++ b/packages/microcosm-build/tests/engine_free/shared/test_nz_target_references.py @@ -111,6 +111,8 @@ def _effective_rows(profile="mar"): _document("target_references.json"), _document("reference_profiles.json"), {"census_residual_allocation": profile, "aging_index": "central"}, + _document("reference_intervals.json"), + factor_context=_document("reference_aging.json"), ) return document["target_references"] @@ -202,6 +204,11 @@ def test_residual_profiles_have_exact_recipient_rosters_and_preserve_other_targe if "households_by_size" in row["name"] } == {*REGIONS, "99"} for before, after in zip(raw, effective, strict=True): + if before["family"] == "income": + assert ( + after["metadata"]["activation_status"] == "requires_prerequisites" + ) + continue if ( before["metadata"]["activation_status"] != "requires_reference_profile_resolution" @@ -261,8 +268,13 @@ def test_full_nz_resource_resolves_directly_to_the_strict_compiler_document(prof raw, _document("reference_profiles.json"), {"census_residual_allocation": profile, "aging_index": "central"}, + _document("reference_intervals.json"), + factor_context=_document("reference_aging.json"), + ) + assert receipt["base_intervals_sha256"] == reference_document_sha256( + _document("reference_intervals.json") ) - assert intervals is None + assert ["scaling" in table for table in intervals["tables"]] == [True, False] assert set(effective) == set(raw) & REFERENCE_DOCUMENT_KEYS references = parse_reference_document(effective, country="nz") assert len(references) == 773 @@ -333,6 +345,91 @@ def test_v4_changes_only_the_residual_knob_and_prior_variants_keep_their_meaning assert knobs["census_residual_allocation"] == ( "small_households" if scenario["id"] == "V4" else "mar" ) + assert knobs["aging_index"] == {"V1": "low", "V2": "high"}.get( + scenario["id"], "central" + ) + + +@pytest.mark.parametrize("profile", ["low", "central", "high"]) +def test_ageing_profiles_have_237_explicit_companions_and_keep_b4_parked(profile): + profiles = _document("reference_profiles.json") + (transformation,) = profiles["dimensions"]["aging_index"]["profiles"][profile][ + "transformations" + ] + expected_counts = [ + f"ird_taxable_income_people_by_band__row_{row}" for row in range(8, 245) + ] + expected_money = [ + f"ird_taxable_income_total_by_band__row_{row}" for row in range(8, 245) + ] + assert transformation["count_reference_names"] == expected_counts + assert transformation["reference_names"] == expected_money + assert transformation["interval_table_ids"] == [ + "ird_taxable_income_national_ty2024" + ] + assert transformation["factor_id"] == f"ird_ty2024_to_ty2027_{profile}" + assert not any("246" in name for name in expected_counts + expected_money) + base = _document("target_references.json") + effective, intervals, receipt = resolve_reference_profiles( + base, + profiles, + {"census_residual_allocation": "mar", "aging_index": profile}, + _document("reference_intervals.json"), + factor_context=_document("reference_aging.json"), + ) + assert intervals["tables"][0]["scaling"]["factor_id"] == ( + f"ird_ty2024_to_ty2027_{profile}" + ) + before = {row["name"]: row for row in base["target_references"]} + after = {row["name"]: row for row in effective["target_references"]} + factor = {"low": 1.115056, "central": 1.117109, "high": 1.119158}[profile] + for count_name, money_name in zip(expected_counts, expected_money, strict=True): + for field in ("ledger_selector", "measure", "filter", "period"): + assert after[count_name][field] == before[count_name][field] + assert after[count_name].get("value_operation") == before[count_name].get( + "value_operation" + ) + assert after[count_name].get("value_operands") == before[count_name].get( + "value_operands" + ) + assert after[money_name]["value_operation"] == "linear_combination" + assert after[money_name]["value_operands"] == [ + { + "aggregate_fact_key": before[money_name]["ledger_selector"][ + "aggregate_fact_key" + ], + "expected_member_count": 1, + "weight": factor, + } + ] + for name in (count_name, money_name): + metadata = after[name]["metadata"] + assert metadata["activation_status"] == "requires_prerequisites" + assert json.loads(metadata["reference_prerequisites_remaining"]) == [ + "measurement:ird_taxable_income_ty2027_v1" + ] + assert receipt["selection"]["aging_index"] == profile + + +def test_resolved_money_uses_the_verified_factor_once_and_count_values_are_unchanged( + artifact, facts_by_key +): + rows = [row for row in _effective_rows() if row["family"] == "income"] + # This numerical operation check supplies activation only to its copies; + # the committed and resolved declarations remain parked on B4. + executable = copy.deepcopy(rows) + for row in executable: + row["metadata"]["activation_status"] = "active" + registry = compile_ledger_target_references( + artifact.facts, _parsed(executable), country="nz" + ) + assert len(registry.specs) == 474 + for row, target in zip(rows, registry.specs, strict=True): + source = facts_by_key[row["ledger_selector"]["aggregate_fact_key"]]["value"] + if row["metadata"]["reference_value_kind"] == "count": + assert target.value == source + else: + assert target.value == pytest.approx(source * 1.117109, rel=1e-12) @pytest.mark.parametrize("profile", ["mar", "small_households"]) @@ -555,7 +652,12 @@ def test_grouped_tenure_family_multiplicities_and_parked_definitions(): == "requires_reference_profile_resolution" ) if row["family"] == "income": - assert row["metadata"]["activation_status"].startswith("requires_g8r2") + assert row["metadata"]["activation_status"] == "requires_prerequisites" + assert json.loads(row["metadata"]["reference_prerequisites"]) == [ + "reference_profile:aging_index", + "measurement:ird_taxable_income_ty2027_v1", + ] + assert row["metadata"]["parking_reason"].startswith("B4:") def test_receipt_snapshots_are_split_and_stratified_inputs_stay_parked(): diff --git a/packages/microcosm-build/tests/engine_free/shared/test_reference_factors.py b/packages/microcosm-build/tests/engine_free/shared/test_reference_factors.py new file mode 100644 index 0000000000..7d97c71a15 --- /dev/null +++ b/packages/microcosm-build/tests/engine_free/shared/test_reference_factors.py @@ -0,0 +1,610 @@ +"""Exact factor arithmetic, evidence and replay without country assumptions.""" + +from copy import deepcopy +from datetime import date +from decimal import Decimal +from fractions import Fraction + +import pytest +from hypothesis import example, given, settings +from hypothesis import strategies as st + +from microcosm.build.ledger_artifact import LexicalFloat +from microcosm.build.reference_factors import ( + certified_nth_root_bounds, + factor_document_sha256, + replay_reference_factor, + require_current_factors, + resolve_reference_factor, + validate_factor_context, +) +from microcosm.graph.canonical import canonical_json +from test_support.microcosm_build.reference_factors import ( + factor_context_fixture, + factor_fixture, +) + + +def _fraction(row): + return Fraction(row["numerator"], row["denominator"]) + + +def _oracle_root(radicand, degree, places=50): + """Independent integer bisection oracle; no production arithmetic helpers.""" + denominator = 10**places + low, high = ( + 0, + max(2, (radicand.numerator // radicand.denominator + 2)) * denominator, + ) + while high - low > 1: + middle = (low + high) // 2 + if ( + middle**degree * radicand.denominator + <= radicand.numerator * denominator**degree + ): + low = middle + else: + high = middle + lower = Fraction(low, denominator) + if lower**degree == radicand: + return lower, lower + return lower, Fraction(high, denominator) + + +def _oracle_round(number, digits): + scaled = number * 10**digits + quotient, remainder = divmod(scaled.numerator, scaled.denominator) + if remainder * 2 > scaled.denominator or ( + remainder * 2 == scaled.denominator and quotient % 2 + ): + quotient += 1 + return quotient + + +def _oracle_factor(source, anchor, growth, frequency, digits, *, places=50): + while places <= 4096: + low, high = _oracle_root(1 + Fraction(growth) / 100, frequency, places) + lower = ( + Fraction(anchor) + / Fraction(source) + * sum(low**index for index in range(frequency)) + / frequency + ) + upper = ( + Fraction(anchor) + / Fraction(source) + * sum(high**index for index in range(frequency)) + / frequency + ) + if _oracle_round(lower, digits) == _oracle_round(upper, digits): + return _oracle_round(lower, digits), (low, high) + places = max(1, places * 2) + raise AssertionError("Independent oracle could not enclose a rounded factor.") + + +def test_independent_oracle_refines_ambiguous_rounding(): + coarse = _oracle_root(Fraction(103, 100), 2, places=1) + assert _oracle_round((1 + coarse[0]) / 2, 6) != _oracle_round( + (1 + coarse[1]) / 2, 6 + ) + expected, bounds = _oracle_factor("1", "1", "3", 2, 6, places=1) + assert expected == 1007445 + assert bounds[1] - bounds[0] < coarse[1] - coarse[0] + + +def test_factor_resolves_exact_operands_once_and_replays(): + context, facts, identity = factor_context_fixture() + entry = context["factors"][0] + receipt = entry["receipt"] + assert entry["operational_factor"] == {"numerator": 1100000, "denominator": 1000000} + assert _fraction(receipt["denominator_mean"]) == 100 + assert receipt["root_bounds"]["exact"] is True + assert [slot["status"] for slot in receipt["target_schedule"]] == [ + "observed", + "projected", + ] + assert all( + slot["numeric_token_proof"]["decimal_values_equal"] + for slot in receipt["source_schedule"] + ) + replay_reference_factor( + entry["declaration"], facts, identity, entry["operational_factor"], receipt + ) + assert validate_factor_context(context, ["toy_factor"]) == {"toy_factor": entry} + + +def test_currency_check_without_selected_factors_is_a_noop(): + require_current_factors({}, today=date(2026, 11, 5)) + + +def test_factor_resolution_and_replay_ignore_caller_feed_pin_prose(): + declaration, facts, identity = factor_fixture() + factor, receipt = resolve_reference_factor(declaration, facts, identity) + pin = { + **identity, + "build": "Reviewed prose edit", + "source_repo": "Reviewed repository description", + } + + revised_factor, revised_receipt = resolve_reference_factor(declaration, facts, pin) + + assert revised_factor == factor + assert revised_receipt == receipt + assert revised_receipt["feed_identity"] == identity + assert declaration["feed_identity"] == identity + replay_reference_factor(declaration, facts, pin, factor, receipt) + + +@pytest.mark.parametrize("container", ["declaration", "context"]) +@pytest.mark.parametrize( + "field", + [ + "source_commit", + "facts_sha256", + "manifest_sha256", + "artifact_schema_version", + "consumer_fact_schema_versions", + "consumer_fact_schema_sha256", + "fact_row_count", + ], +) +def test_factor_identity_requires_every_authenticated_field(container, field): + context, facts, identity = factor_context_fixture() + declaration = context["factors"][0]["declaration"] + document = declaration if container == "declaration" else context + document["feed_identity"] = { + key: value for key, value in document["feed_identity"].items() if key != field + } + + with pytest.raises(ValueError, match="missing fields"): + if container == "declaration": + resolve_reference_factor(declaration, facts, identity) + else: + validate_factor_context(context) + + +@pytest.mark.parametrize("container", ["declaration", "context"]) +@pytest.mark.parametrize("field", ["build", "source_repo"]) +def test_factor_declared_identity_refuses_prose_fields(container, field): + context, facts, identity = factor_context_fixture() + declaration = context["factors"][0]["declaration"] + document = declaration if container == "declaration" else context + document["feed_identity"] = {**document["feed_identity"], field: "Prose"} + + with pytest.raises(ValueError, match="Unknown factor .*feed identity fields"): + if container == "declaration": + resolve_reference_factor(declaration, facts, identity) + else: + validate_factor_context(context) + + +def test_irrational_root_is_an_enclosure_never_an_exact_rational(): + expected, _ = _oracle_factor("100", "110", "3", 4, 6) + declaration, facts, identity = factor_fixture( + frequency=4, growth="3", expected_numerator=expected + ) + _, receipt = resolve_reference_factor(declaration, facts, identity) + bounds = receipt["root_bounds"] + lower, upper = _fraction(bounds["lower"]), _fraction(bounds["upper"]) + assert bounds["exact"] is False + assert lower < upper + assert lower**4 < Fraction(103, 100) < upper**4 + factor_bounds = receipt["unrounded_factor_bounds"] + assert _oracle_round(_fraction(factor_bounds["lower"]), 6) == expected + assert _oracle_round(_fraction(factor_bounds["upper"]), 6) == expected + + +def test_exact_root_is_recognized_without_false_irrationality(): + lower, upper, exact = certified_nth_root_bounds(Fraction(121, 100), 2, 8) + assert lower == upper == Fraction(11, 10) + assert exact is True + + +@pytest.mark.parametrize( + "anchor,expected", [("2469135", 1234568), ("2469133", 1234566)] +) +def test_single_final_rounding_uses_nearest_half_even(anchor, expected): + declaration, facts, identity = factor_fixture( + frequency=1, + source_level="2000000", + anchor_level=anchor, + expected_numerator=expected, + ) + factor, _ = resolve_reference_factor(declaration, facts, identity) + assert factor["numerator"] == expected + + +def test_observed_only_diagnostic_needs_no_projection_operand(): + declaration, facts, identity = factor_fixture() + observed = deepcopy(facts[-2]) + observed["aggregate_fact_key"] = "target-1" + observed["period"]["value"] = declaration["target_schedule"][1]["selector"][ + "period_value" + ] + observed["period_coverage"] = declaration["target_schedule"][1]["validation"][ + "period_coverage" + ] + facts.append(observed) + declaration["purpose"] = "diagnostic" + declaration["growth"] = None + factor, receipt = resolve_reference_factor(declaration, facts, identity) + assert factor["numerator"] == 1100000 + assert receipt["growth"] is None + assert all(slot["status"] == "observed" for slot in receipt["target_schedule"]) + + +@pytest.mark.parametrize( + "field,mutation,message", + [ + ("operation", "expression_eval", "operation"), + ("operation_version", 2, "operation"), + ("schema_version", 2, "schema_version"), + ("unknown", "field", "Unknown"), + ("subperiods_per_year", True, "subperiods_per_year"), + ("subperiods_per_year", 0, "subperiods_per_year"), + ("projection_policy", "june_anchor", "projection policy"), + ("purpose", "execute", "purpose"), + ("source_period", True, "period labels"), + ("target_period", None, "period labels"), + ("source_period", "", "period labels"), + ], +) +def test_closed_declaration_guards(field, mutation, message): + declaration, facts, identity = factor_fixture() + declaration[field] = mutation + with pytest.raises(ValueError, match=message): + resolve_reference_factor(declaration, facts, identity) + + +@pytest.mark.parametrize( + "mutation,message", + [ + ("missing", "exactly once"), + ("duplicate", "Duplicate"), + ("unit", "unit mismatch"), + ("source_sha256", "source_sha256 mismatch"), + ("source_vintage", "source_vintage mismatch"), + ("entity_role", "entity_role mismatch"), + ("coverage", "coverage mismatch"), + ("boolean", "Boolean"), + ("nan", "finite"), + ("float_without_token", "lexical_floats=True"), + ("lossy_float", "does not reproduce"), + ("negative", "positive"), + ], +) +def test_operand_guards(mutation, message): + declaration, facts, identity = factor_fixture() + if mutation == "missing": + facts.pop(0) + elif mutation == "duplicate": + duplicate = deepcopy(facts[0]) + duplicate["aggregate_fact_key"] += "-duplicate" + facts.append(duplicate) + elif mutation == "unit": + facts[0]["observed_measure"]["unit"] = "other" + elif mutation == "source_sha256": + facts[0]["source"]["source_sha256"] = "b" * 64 + elif mutation == "source_vintage": + facts[0]["source"]["vintage"] = "revised" + elif mutation == "entity_role": + facts[0]["entity"]["role"] = "other" + elif mutation == "coverage": + facts[0]["period_coverage"]["end_date"] = "2001-02-01" + # The fixture shares this dictionary with its declaration; keep the pin. + declaration["source_schedule"][0]["validation"]["period_coverage"][ + "end_date" + ] = "2001-01-01" + facts[0]["period_coverage"] = { + "start_date": "2001-01-01", + "end_date": "2001-02-01", + } + elif mutation == "boolean": + facts[0]["value"] = True + elif mutation == "nan": + facts[0]["value"] = Decimal("NaN") + elif mutation == "float_without_token": + facts[0]["value"] = 100.0 + elif mutation == "lossy_float": + facts[0]["value"] = LexicalFloat("100.000000000000000001") + elif mutation == "negative": + facts[0]["value"] = Decimal("-1") + with pytest.raises(ValueError, match=message): + resolve_reference_factor(declaration, facts, identity) + + +def test_lexical_float_conversion_is_proved_and_used_exactly(): + declaration, facts, identity = factor_fixture( + source_level="100.25", anchor_level="110.275", expected_numerator=1100000 + ) + for fact in facts: + fact["value"] = LexicalFloat(str(fact["value"])) + _, receipt = resolve_reference_factor(declaration, facts, identity) + proof = receipt["source_schedule"][0]["numeric_token_proof"] + assert proof == { + "numeric_representation": "binary_float_with_lexical_token", + "lexical_token": "100.25", + "recovered_decimal": "100.25", + "decimal_values_equal": True, + } + assert _fraction(receipt["denominator_mean"]) == Fraction(401, 4) + + +def test_integer_operands_are_exact_beyond_binary_float_precision(): + source = 10**80 + 10 + anchor = source * 11 // 10 + declaration, facts, identity = factor_fixture( + source_level=str(source), + anchor_level=str(anchor), + expected_numerator=1100000, + ) + for fact in facts: + fact["value"] = int(fact["value"]) + + factor, receipt = resolve_reference_factor(declaration, facts, identity) + + assert factor == {"numerator": 1100000, "denominator": 1000000} + assert _fraction(receipt["denominator_mean"]) == source + assert _fraction(receipt["numerator_mean_bounds"]["lower"]) == anchor + assert _fraction(receipt["numerator_mean_bounds"]["upper"]) == anchor + operands = [ + *receipt["source_schedule"], + *(slot for slot in receipt["target_schedule"] if slot["status"] == "observed"), + receipt["growth"], + ] + for operand in operands: + token = operand["decimal_operand"] + assert operand["numeric_token_proof"] == { + "numeric_representation": "exact_integer", + "lexical_token": token, + "recovered_decimal": token, + "decimal_values_equal": True, + } + assert receipt["source_schedule"][0]["decimal_operand"] == str(source) + assert receipt["target_schedule"][0]["decimal_operand"] == str(anchor) + + +def test_source_projection_requires_existing_allow_guard_even_with_exact_key(): + declaration, facts, identity = factor_fixture() + declaration["growth"]["assertion_policy"] = "observed_only" + with pytest.raises(ValueError, match="allow_source_projection"): + resolve_reference_factor(declaration, facts, identity) + + +@pytest.mark.parametrize( + "mutation,message", + [ + ("schedule_order", "misordered"), + ("duplicate_period", "Duplicate"), + ("schedule_gap", "noncontiguous"), + ("negative_weight", "positive"), + ("offset", "projection offsets"), + ("unknown_selector", "selector"), + ("growth_floor", "positive 1"), + ("sensitivity", "sensitivity provenance"), + ("expired", "expired"), + ("wrong_expected", "expected factor mismatch"), + ("wrong_feed", "feed identity"), + ("wrong_growth_period", "exactly once"), + ("source_column", "source_column_id mismatch"), + ], +) +def test_numeric_and_schedule_guards(mutation, message): + declaration, facts, identity = factor_fixture() + if mutation == "schedule_order": + declaration["source_schedule"].reverse() + elif mutation == "duplicate_period": + declaration["source_schedule"][1]["selector"]["period_value"] = "2001-01-01" + elif mutation == "schedule_gap": + declaration["source_schedule"][1]["validation"]["period_coverage"][ + "start_date" + ] = "2001-01-04" + elif mutation == "negative_weight": + declaration["source_schedule"][0]["weight"] = "-1" + elif mutation == "offset": + declaration["target_schedule"][1]["projection_offset"] = 0 + elif mutation == "unknown_selector": + declaration["source_schedule"][0]["selector"]["unit"] = "money_per_week" + elif mutation == "growth_floor": + facts[-1]["value"] = Decimal("-100") + elif mutation == "sensitivity": + declaration["growth"]["sensitivity_provenance"] = [] + elif mutation == "expired": + declaration["validity"]["valid_until"] = "2001-12-31" + elif mutation == "wrong_expected": + declaration["expected_operational_factor"]["numerator"] += 1 + elif mutation == "wrong_feed": + identity = {**identity, "facts_sha256": "wrong"} + elif mutation == "wrong_growth_period": + declaration["growth"]["selector"]["period_value"] = "2003" + elif mutation == "source_column": + declaration["growth"]["validation"]["source_column_id"] = "wrong" + with pytest.raises(ValueError, match=message): + resolve_reference_factor(declaration, facts, identity) + + +def test_observed_preferred_requires_redeclaration_and_reanchors_projection(): + declaration, facts, identity = factor_fixture(frequency=4) + observed = deepcopy(facts[-2]) + observed["aggregate_fact_key"] = "target-1" + observed["value"] = Decimal("120") + observed["period"]["value"] = declaration["target_schedule"][1]["selector"][ + "period_value" + ] + observed["period_coverage"] = declaration["target_schedule"][1]["validation"][ + "period_coverage" + ] + facts.append(observed) + with pytest.raises(ValueError, match="expected factor mismatch"): + resolve_reference_factor(declaration, facts, identity) + # Growth zero makes the latest-anchor formula transparent: (110+120+120+120)/4. + declaration["expected_operational_factor"]["numerator"] = 1175000 + _, receipt = resolve_reference_factor(declaration, facts, identity) + assert _fraction(receipt["numerator_mean_bounds"]["lower"]) == Fraction(470, 4) + assert [slot["projection_offset"] for slot in receipt["target_schedule"]] == [ + 0, + 0, + 1, + 2, + ] + assert receipt["target_schedule"][2]["projection_anchor"] == { + "aggregate_fact_key": "target-1" + } + + +def test_observed_gap_refuses_instead_of_guessing_anchor(): + declaration, facts, identity = factor_fixture(frequency=4) + observed = deepcopy(facts[-2]) + observed["period"]["value"] = declaration["target_schedule"][2]["selector"][ + "period_value" + ] + observed["period_coverage"] = declaration["target_schedule"][2]["validation"][ + "period_coverage" + ] + facts.append(observed) + with pytest.raises(ValueError, match="contiguous from the anchor"): + resolve_reference_factor(declaration, facts, identity) + + +def test_self_consistent_receipt_cannot_replace_compile_replay(): + context, facts, identity = factor_context_fixture() + entry = context["factors"][0] + entry["declaration"]["expected_operational_factor"]["numerator"] = 1200000 + entry["operational_factor"]["numerator"] = 1200000 + entry["receipt"]["operational_factor"]["numerator"] = 1200000 + entry["receipt"]["declaration_sha256"] = factor_document_sha256( + entry["declaration"] + ) + entry["receipt"]["receipt_sha256"] = factor_document_sha256( + { + key: value + for key, value in entry["receipt"].items() + if key != "receipt_sha256" + } + ) + assert validate_factor_context(context, ["toy_factor"]) + with pytest.raises(ValueError, match="expected factor mismatch"): + replay_reference_factor( + entry["declaration"], + facts, + identity, + entry["operational_factor"], + entry["receipt"], + ) + + +def test_receipt_tampering_refuses_and_unselected_edits_are_local(): + context, _, _ = factor_context_fixture() + other = deepcopy(context["factors"][0]) + other["declaration"]["id"] = "unused" + other["receipt"]["receipt_sha256"] = "invalid" + context["factors"].append(other) + assert list(validate_factor_context(context, ["toy_factor"])) == ["toy_factor"] + with pytest.raises(ValueError, match="hash mismatch"): + validate_factor_context(context, ["unused"]) + + +@settings(max_examples=70, deadline=None) +@example(source=32, anchor=1, growth=0, frequency=2, digits=4) +@given( + source=st.integers(1, 10**9), + anchor=st.integers(1, 10**9), + growth=st.integers(-49, 49), + frequency=st.sampled_from([1, 2, 4, 12]), + digits=st.sampled_from([4, 6, 8]), +) +def test_certified_rounding_and_root_bounds_match_independent_fraction_oracle( + source, anchor, growth, frequency, digits +): + source_text, anchor_text = str(Decimal(source) / 100), str(Decimal(anchor) / 100) + expected, oracle_bounds = _oracle_factor( + source_text, anchor_text, str(growth), frequency, digits + ) + declaration, facts, identity = factor_fixture( + source_level=source_text, + anchor_level=anchor_text, + growth=str(growth), + frequency=frequency, + digits=digits, + expected_numerator=expected, + ) + if expected == 0: + with pytest.raises( + ValueError, match="Expected operational factor must be positive" + ): + resolve_reference_factor(declaration, facts, identity) + return + factor, receipt = resolve_reference_factor(declaration, facts, identity) + assert factor["numerator"] == expected + lower, upper = ( + _fraction(receipt["root_bounds"]["lower"]), + _fraction(receipt["root_bounds"]["upper"]), + ) + radicand = 1 + Fraction(growth, 100) + assert lower**frequency <= radicand <= upper**frequency + assert lower <= oracle_bounds[1] and upper >= oracle_bounds[0] + if receipt["root_bounds"]["exact"]: + assert lower == upper and lower**frequency == radicand + else: + assert lower < upper + + +def test_very_large_integer_cross_products_do_not_overflow(): + huge = 10**200 + declaration, facts, identity = factor_fixture( + source_level=str(huge), + anchor_level=str(3 * huge), + frequency=12, + expected_numerator=3000000, + ) + factor, receipt = resolve_reference_factor(declaration, facts, identity) + assert factor["numerator"] == 3000000 + assert _fraction(receipt["denominator_mean"]) == huge + + +@pytest.mark.parametrize( + "frequency,digits,message", + [ + (13, 6, "subperiods_per_year.*1 to 12.*serializable"), + (365, 6, "subperiods_per_year.*1 to 12.*serializable"), + (12, 19, "rounding digits.*0 to 18.*serializable"), + ], +) +def test_unsupported_exact_receipt_schedule_refuses_at_declaration( + frequency, digits, message +): + declaration, facts, identity = factor_fixture() + declaration["subperiods_per_year"] = frequency + declaration["rounding"]["digits"] = digits + # A malformed schedule is intentional: range validation must precede it. + declaration["source_schedule"] = [] + with pytest.raises(ValueError, match=message): + resolve_reference_factor(declaration, facts, identity) + + +def test_largest_supported_schedule_and_rounding_have_serializable_exact_receipt(): + expected, _ = _oracle_factor("100", "110", "3", 12, 18) + declaration, facts, identity = factor_fixture( + frequency=12, growth="3", digits=18, expected_numerator=expected + ) + factor, receipt = resolve_reference_factor(declaration, facts, identity) + assert factor == {"numerator": expected, "denominator": 10**18} + encoded = canonical_json(receipt) + assert encoded and factor_document_sha256(receipt) + replay_reference_factor(declaration, facts, identity, factor, receipt) + + +def test_root_refinement_stays_within_exact_receipt_precision_budget(monkeypatch): + precisions = [] + + def ambiguous_bounds(value, degree, decimal_places): + precisions.append(decimal_places) + return Fraction(1), Fraction(2), False + + monkeypatch.setattr( + "microcosm.build.reference_factors.certified_nth_root_bounds", ambiguous_bounds + ) + declaration, facts, identity = factor_fixture(frequency=12, digits=18) + with pytest.raises(ValueError, match="supported exact receipt precision"): + resolve_reference_factor(declaration, facts, identity) + assert precisions == [26, 52, 104, 208] diff --git a/packages/microcosm-build/tests/engine_free/shared/test_reference_intervals.py b/packages/microcosm-build/tests/engine_free/shared/test_reference_intervals.py new file mode 100644 index 0000000000..71a02b046c --- /dev/null +++ b/packages/microcosm-build/tests/engine_free/shared/test_reference_intervals.py @@ -0,0 +1,1173 @@ +"""Exact interval cuts, declared semantics, indicators and boundary diagnostics. + +The Hypothesis oracle below reads cuts itself with ``fractions.Fraction`` and +never calls a production helper. +""" + +from __future__ import annotations + +import copy +import json +from decimal import Decimal +from fractions import Fraction + +import numpy as np +import pandas as pd +import pytest +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st + +from microcosm.build.reference_intervals import ( + BELOW_FIRST_CUT, + EXCLUDED, + IntervalPreparationError, + boundary_diagnostics, + classify_records, + frame_boundary_diagnostics, + interval_document_sha256, + interval_indicators, + interval_input_fingerprint, + interval_table, + scale_interval_document, + scale_interval_table, + source_interval_table, + validate_interval_document, +) +from microcosm.frame import EntitySchema, Frame, WeightKind, Weights + +CENTRAL = {"numerator": 1117109, "denominator": 1000000} +_SETTINGS = settings( + max_examples=60, + database=None, + deadline=None, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) + + +def _table( + cuts=(10_000, 100_000), + *, + closure="right", + nil=True, + first=0, + entity="person", + policy="floor_zero", + table_id="table", + window=100, + income="income_cents", + universe="universe_status", +): + bands = [] + if nil: + bands.append({"id": "nil", "kind": "nil", "indicator": f"{table_id}_nil"}) + for index, cut in enumerate((*cuts, None)): + bands.append( + { + "id": f"b{index}", + "kind": "positive", + "upper_cent": cut, + "indicator": f"{table_id}_b{index}", + } + ) + return { + "id": table_id, + "entity": entity, + "currency": "XTS", + "input_unit": "integer_cent", + "income_column": income, + "universe_column": universe, + "source_period": 2001, + "target_period": 2001, + "positive_band_closure": closure, + "nil_band": "present" if nil else "absent", + "negative_income_policy": policy, + "first_lower_cut_cents": first, + "source_locator": "Toy!A1:A9", + "diagnostics": { + "boundary_window_cents": window, + "alternative_positive_band_closure": "left" + if closure == "right" + else "right", + }, + "bands": bands, + } + + +def _scale(table, factor=CENTRAL): + return scale_interval_table( + table, + factor, + factor_id="toy_factor", + factor_declaration_sha256="a" * 64, + factor_receipt_sha256="b" * 64, + ) + + +def _ids(table, positions): + parsed = interval_table(table) + return [ + {BELOW_FIRST_CUT: "below", EXCLUDED: "excluded"}.get( + position, parsed.band_ids[position] if position >= 0 else None + ) + for position in positions + ] + + +def _classify(table, amounts, universe=None, **kwargs): + universe = ["included"] * len(amounts) if universe is None else universe + return _ids( + table, classify_records(interval_table(table), amounts, universe, **kwargs) + ) + + +# --------------------------------------------------------------------------- +# Example tests +# --------------------------------------------------------------------------- + + +@pytest.mark.parametrize( + ("closure", "expected"), + [ + ( + "right", + ["nil", "nil", "b0", "b0", "b0", "b1", "b1", "b1", "b2"], + ), + ( + "left", + ["nil", "nil", "b0", "b0", "b1", "b1", "b1", "b2", "b2"], + ), + ], +) +def test_each_exact_cut_and_one_cent_either_side(closure, expected): + table = _table(closure=closure) + amounts = [-1, 0, 1, 9_999, 10_000, 10_001, 99_999, 100_000, 100_001] + assert _classify(table, amounts) == expected + + +@pytest.mark.parametrize( + ("closure", "zero", "last", "above"), + [("right", "below", "b1", "b2"), ("left", "b0", "b2", "b2")], +) +def test_first_positive_band_and_open_tail_under_both_closures( + closure, zero, last, above +): + table = _table(closure=closure, nil=False) + assert _classify(table, [0, 1, 100_000, 100_001]) == [zero, "b0", last, above] + + +@pytest.mark.parametrize("closure", ["right", "left"]) +@pytest.mark.parametrize("nil", [False, True]) +def test_a_table_starting_above_zero_reports_records_below_its_first_cut(closure, nil): + table = _table((5_000_000,), closure=closure, nil=nil, first=4_000_000) + amounts = [0, 3_999_999, 4_000_000, 4_000_001, 5_000_000, 5_000_001] + at_first = "below" if closure == "right" else "b0" + at_upper = "b0" if closure == "right" else "b1" + assert _classify(table, amounts) == [ + "nil" if nil else "below", + "below", + at_first, + "b0", + at_upper, + "b1", + ] + report = boundary_diagnostics( + interval_table(table), + list(range(6)), + amounts, + ["included"] * 6, + [1.0] * 6, + weight_record_ids=list(range(6)), + weight_kind="design", + ) + assert report["below_first_cut"]["declared"]["records"] == ( + 2 if closure == "right" else 1 + ) + (0 if nil else 1) + assert Fraction(**report["below_first_cut"]["declared"]["weighted_count"]) == ( + 2 if closure == "right" else 1 + ) + (0 if nil else 1) + assert Fraction( + **report["below_first_cut"]["declared"]["weighted_amount_cents"] + ) == 3_999_999 + (4_000_000 if closure == "right" else 0) + assert report["cuts"][0]["cut"] == "first_lower_cut" + assert report["cuts"][0]["source_cut_cents"] == 4_000_000 + + +def test_nil_and_loss_records_follow_the_declared_negative_policy(): + assert _classify(_table(), [-123_456, 0, 1]) == ["nil", "nil", "b0"] + with pytest.raises(IntervalPreparationError) as refused: + classify_records( + interval_table(_table(policy="refuse")), [-1, 0, 5], ["included"] * 3 + ) + assert refused.value.summary["reasons"] == {"negative_amount_refused": 1} + # Excluded losses never enter a band under either policy. + assert _classify(_table(policy="refuse"), [-1], ["excluded"]) == ["excluded"] + + +@pytest.mark.parametrize("scaled", [False, True]) +def test_left_closed_nil_table_with_a_zero_first_cut_puts_zero_in_nil_only(scaled): + # Zero is nil under either closure, so the first positive band is + # 0 < z < upper. Scaling keeps the zero cut: one cent stays in b0 rather + # than falling below a nonzero stand-in cut. + table = _table((100, 1_000), closure="left") + amounts = [-1, 0, 1, 99, 100, 999, 1_000, 1_001] + if scaled: + table = _scale(table, {"numerator": 2, "denominator": 1}) + assert table["first_lower_cut_cents"] == {"numerator": 0, "denominator": 1} + amounts = [-1, 0, 1, 199, 200, 1_999, 2_000, 2_001] + assert _classify(table, amounts) == [ + "nil", + "nil", + "b0", + "b0", + "b1", + "b1", + "b2", + "b2", + ] + + +def test_left_closed_nil_zero_first_cut_diagnostics_keep_zero_in_nil(): + table = interval_table(_table((100, 1_000), closure="left")) + report = boundary_diagnostics( + table, + [0, 1, 2, 3], + [-5, 0, 1, 100], + ["included"] * 4, + [2.0, 3.0, 5.0, 7.0], + weight_record_ids=[0, 1, 2, 3], + weight_kind="design", + ) + bands = {band["band"]: band for band in report["bands"]} + assert bands["nil"]["declared"]["records"] == 2 + assert Fraction(**bands["nil"]["declared"]["weighted_count"]) == 5 + assert "alternative" not in bands["nil"] + # Declared left: 1 is b0 and 100 is b1. The right-closed alternative puts + # both in b0; zero stays nil and nothing is below the first cut. + assert [bands[band]["declared"]["records"] for band in ("b0", "b1", "b2")] == [ + 1, + 1, + 0, + ] + assert [bands[band]["alternative"]["records"] for band in ("b0", "b1", "b2")] == [ + 2, + 0, + 0, + ] + assert report["below_first_cut"]["declared"]["records"] == 0 + assert report["below_first_cut"]["alternative"]["records"] == 0 + + +def test_left_closed_nil_table_keeps_a_positive_fractional_first_cut_after_scaling(): + effective = _scale( + _table(closure="left", first=1), {"numerator": 1, "denominator": 2} + ) + assert effective["first_lower_cut_cents"] == {"numerator": 1, "denominator": 2} + assert _classify(effective, [-1, 0, 1]) == ["nil", "nil", "b0"] + + +def test_right_closed_nil_diagnostics_keep_zero_out_of_the_left_closed_alternative(): + table = interval_table(_table()) + report = boundary_diagnostics( + table, + [0, 1], + [-5, 0], + ["included", "included"], + [2.0, 3.0], + weight_record_ids=[0, 1], + weight_kind="design", + ) + bands = {band["band"]: band for band in report["bands"]} + assert bands["nil"]["declared"]["records"] == 2 + for band in table.band_ids[1:]: + assert bands[band]["declared"]["records"] == 0 + assert bands[band]["alternative"]["records"] == 0 + assert report["below_first_cut"]["alternative"]["records"] == 0 + + +@pytest.mark.parametrize( + ("closure", "nil", "first", "declared_destination", "alternative_destination"), + [ + ("right", True, 0, "nil", "nil"), + ("right", True, 10, "nil", "nil"), + ("left", True, 1, "nil", "nil"), + ("right", False, 1, "below_first_cut", "below_first_cut"), + ("left", False, 1, "below_first_cut", "below_first_cut"), + ("right", False, 0, "none", "b0"), + ("left", False, 0, "b0", "none"), + ], +) +def test_floored_negative_mass_reports_signed_amounts_by_actual_destination( + closure, nil, first, declared_destination, alternative_destination +): + report = boundary_diagnostics( + interval_table(_table(closure=closure, nil=nil, first=first)), + [0, 1, 2, 3, 4], + [-120, -30, -999, 0, 1], + ["included", "included", "excluded", "included", "included"], + [2.0, 0.5, 99.0, 3.0, 4.0], + weight_record_ids=[0, 1, 2, 3, 4], + weight_kind="design", + ) + floored = report["floored_negative_income"] + expected = { + "records": 2, + "weighted_count": {"numerator": 5, "denominator": 2}, + "pre_floor_amount_cents": -150, + "weighted_pre_floor_amount_cents": {"numerator": -255, "denominator": 1}, + } + assert {key: floored[key] for key in expected} == expected + for evaluation, destination in ( + ("declared", declared_destination), + ("alternative", alternative_destination), + ): + destinations = floored["by_destination"][evaluation] + actual = ( + destinations["positive_bands"][destination] + if destination == "b0" + else destinations[destination] + ) + assert actual == expected + all_destinations = [ + destinations["nil"], + destinations["below_first_cut"], + destinations["none"], + *destinations["positive_bands"].values(), + ] + assert sum(row["records"] for row in all_destinations) == 2 + assert sum(row["pre_floor_amount_cents"] for row in all_destinations) == -150 + for measure in ("weighted_count", "weighted_pre_floor_amount_cents"): + assert sum( + Fraction(**row[measure]) for row in all_destinations + ) == Fraction(**expected[measure]) + + +def test_a_band_id_cannot_merge_with_the_below_first_cut_diagnostic_bucket(): + declaration = _table(first=100) + declaration["bands"][1]["id"] = "below_first_cut" + report = boundary_diagnostics( + interval_table(declaration), + [0, 1], + [50, 101], + ["included", "included"], + [2.0, 3.0], + weight_record_ids=[0, 1], + weight_kind="design", + ) + band = next(row for row in report["bands"] if row["band"] == "below_first_cut") + assert band["declared"]["weighted_count"] == {"numerator": 3, "denominator": 1} + assert report["below_first_cut"]["declared"]["weighted_count"] == { + "numerator": 2, + "denominator": 1, + } + + +def test_fractional_cent_aged_cuts_stay_exact_and_are_never_rounded(): + effective = _scale(_table((10_000, 100_000, 4_000_000))) + uppers = [band.get("upper_cent") for band in effective["bands"]] + assert uppers == [ + None, + {"numerator": 1117109, "denominator": 100}, + {"numerator": 1117109, "denominator": 10}, + {"numerator": 4468436, "denominator": 1}, + None, + ] + assert Fraction(1117109, 100) == Fraction("11171.09") + assert Fraction(1117109, 10) == Fraction("111710.9") + # $111.7109: 11,171 cents is inside the first band and 11,172 above it. + # $1,117.109: 111,710 cents is inside, and 111,711 lies above the cut. + assert _classify(effective, [11_171, 11_172, 111_710, 111_711]) == [ + "b0", + "b1", + "b1", + "b2", + ] + assert _classify(effective, [4_468_436, 4_468_437]) == ["b2", "b3"] + assert effective["scaling"]["operational_factor"] == CENTRAL + assert source_interval_table(effective) == _table((10_000, 100_000, 4_000_000)) + + +def test_included_excluded_and_unresolved_routes(): + table = interval_table(_table()) + indicators = interval_indicators( + table, [0, 0, 500, 500_000], ["included", "excluded", "included", "excluded"] + ) + assert {name: values.tolist() for name, values in indicators.items()} == { + "table_nil": [True, False, False, False], + "table_b0": [False, False, True, False], + "table_b1": [False, False, False, False], + "table_b2": [False, False, False, False], + } + with pytest.raises(IntervalPreparationError) as refused: + interval_indicators( + table, [1, 2, 3, 4], ["included", "unresolved", "maybe", None] + ) + assert refused.value.summary == { + "table": "table", + "entity": "person", + "records": 4, + "refused_records": 3, + "reasons": {"invalid_universe_status": 2, "unresolved_universe_status": 1}, + "universe_statuses": {"included": 1, "invalid": 2, "unresolved": 1}, + } + + +@pytest.mark.parametrize( + ("amount", "reason"), + [ + (True, "boolean_amount"), + (np.bool_(False), "boolean_amount"), + (1.0, "non_integer_amount"), + (np.float64(250.0), "non_integer_amount"), + ("100", "text_amount"), + (None, "missing_amount"), + (float("nan"), "missing_amount"), + (float("inf"), "nonfinite_amount"), + (pd.NA, "missing_amount"), + (Decimal("100"), "non_integer_amount"), + (Fraction(1, 2), "non_integer_amount"), + ], +) +def test_booleans_floats_strings_and_missing_amounts_refuse(amount, reason): + table = interval_table(_table()) + with pytest.raises(IntervalPreparationError) as refused: + interval_indicators(table, [10, amount], ["included", "included"]) + assert refused.value.summary["reasons"] == {reason: 1} + # An excluded record's amount is never read. + assert interval_indicators(table, [10, amount], ["included", "excluded"])[ + "table_b0" + ].tolist() == [True, False] + + +def test_signed_numpy_and_python_integers_classify_identically(): + table = interval_table(_table()) + expected = classify_records(table, [-5, 0, 10_000], ["included"] * 3) + assert ( + classify_records( + table, list(np.asarray([-5, 0, 10_000], dtype=np.int64)), ["included"] * 3 + ) + == expected + ) + + +@pytest.mark.parametrize( + "field", + [ + "positive_band_closure", + "nil_band", + "negative_income_policy", + "first_lower_cut_cents", + "input_unit", + "income_column", + "universe_column", + "entity", + "currency", + "source_period", + "target_period", + "source_locator", + "diagnostics", + ], +) +def test_every_semantic_is_declared_and_none_has_a_default(field): + table = _table() + table.pop(field) + with pytest.raises(ValueError, match="missing declared fields"): + interval_table(table) + + +@pytest.mark.parametrize( + ("field", "value"), + [ + ("positive_band_closure", "both"), + ("positive_band_closure", True), + ("nil_band", True), + ("nil_band", "maybe"), + ("negative_income_policy", "absolute"), + ("input_unit", "float_dollar"), + ("first_lower_cut_cents", -1), + ("first_lower_cut_cents", 0.0), + ("first_lower_cut_cents", False), + ("source_period", True), + ("income_column", "universe_status"), + ], +) +def test_invalid_declared_semantics_refuse(field, value): + table = _table() + table[field] = value + with pytest.raises(ValueError): + interval_table(table) + + +def test_the_diagnostic_alternative_is_the_other_closure(): + table = _table(closure="left") + assert table["diagnostics"]["alternative_positive_band_closure"] == "right" + interval_table(table) + table["diagnostics"]["alternative_positive_band_closure"] = "left" + with pytest.raises(ValueError, match="other positive band closure"): + interval_table(table) + + +@pytest.mark.parametrize( + "cut", + [ + 10_000.0, + float("inf"), + float("nan"), + True, + "10000", + json.loads('{"x": Infinity}')["x"], + json.loads('{"x": NaN}')["x"], + -5, + 0, + ], +) +def test_floats_booleans_nonfinite_and_nonpositive_source_cuts_refuse(cut): + table = _table() + table["bands"][1]["upper_cent"] = cut + with pytest.raises(ValueError): + interval_table(table) + + +@pytest.mark.parametrize( + "rational", + [ + {"numerator": 2234218, "denominator": 200}, + {"numerator": 1117109, "denominator": 0}, + {"numerator": 1117109, "denominator": -100}, + {"numerator": 1117109.0, "denominator": 100}, + {"numerator": True, "denominator": 1}, + {"numerator": 1117109, "denominator": 100, "extra": 1}, + ], +) +def test_effective_cuts_must_be_reduced_integer_rationals(rational): + effective = _scale(_table()) + effective["bands"][1]["upper_cent"] = rational + with pytest.raises(ValueError): + interval_table(effective) + + +@pytest.mark.parametrize( + "defect", + [ + "decreasing", + "repeated", + "below_first", + "two_tails", + "tail_not_last", + "no_tail", + "nil_not_first", + "nil_declared_absent", + "nil_missing", + "duplicate_band", + "duplicate_indicator", + "unknown_kind", + "partial_companions", + "mixed_companions", + "unknown_field", + ], +) +def test_malformed_band_structures_refuse(defect): + table = _table((10_000, 100_000, 200_000)) + bands = table["bands"] + if defect == "decreasing": + bands[2]["upper_cent"] = 5_000 + elif defect == "repeated": + bands[2]["upper_cent"] = 10_000 + elif defect == "below_first": + table["first_lower_cut_cents"] = 10_000 + elif defect == "two_tails": + bands[2]["upper_cent"] = None + elif defect == "tail_not_last": + bands[-1], bands[-2] = bands[-2], bands[-1] + elif defect == "no_tail": + bands.pop() + elif defect == "nil_not_first": + bands.append(bands.pop(0)) + elif defect == "nil_declared_absent": + table["nil_band"] = "absent" + elif defect == "nil_missing": + bands.pop(0) + elif defect == "duplicate_band": + bands[2]["id"] = bands[1]["id"] + elif defect == "duplicate_indicator": + bands[2]["indicator"] = bands[1]["indicator"] + elif defect == "unknown_kind": + bands[1]["kind"] = "finite" + elif defect == "partial_companions": + bands[1]["count_reference"] = "count_1" + elif defect == "mixed_companions": + bands[1].update(count_reference="count_1", amount_reference="amount_1") + else: + bands[1]["lower_cent"] = 0 + with pytest.raises(ValueError): + interval_table(table) + + +def test_documents_require_unique_tables_indicators_and_references(): + first = _table(table_id="first") + second = _table(table_id="second", entity="household") + validate_interval_document({"schema_version": 1, "tables": [first, second]}) + for defect in ("table", "indicator", "reference", "schema", "unknown"): + tables = [copy.deepcopy(first), copy.deepcopy(second)] + document = {"schema_version": 1, "tables": tables} + if defect == "table": + tables[1]["id"] = "first" + elif defect == "indicator": + tables[1]["bands"][1]["indicator"] = tables[0]["bands"][1]["indicator"] + elif defect == "reference": + for table in tables: + for index, band in enumerate(table["bands"]): + band.update( + count_reference=f"{table['id']}_count_{index}", + amount_reference=f"{table['id']}_amount_{index}", + ) + tables[1]["bands"][1]["count_reference"] = "first_count_1" + elif defect == "schema": + document["schema_version"] = True + else: + document["defaults"] = {"positive_band_closure": "right"} + with pytest.raises(ValueError): + validate_interval_document(document) + + +def test_scaling_twice_refuses_and_scaled_cuts_bind_their_source(): + source = _table() + effective = _scale(source) + with pytest.raises(ValueError, match="already scaled"): + _scale(effective) + with pytest.raises(ValueError, match="cannot contain scaled tables"): + scale_interval_document( + {"schema_version": 1, "tables": [effective]}, {"table": {}} + ) + twice = copy.deepcopy(effective) + factor = Fraction(1117109, 1000000) + for band in twice["bands"]: + if band.get("upper_cent") is not None: + value = ( + Fraction(band["upper_cent"]["numerator"], 1) + / band["upper_cent"]["denominator"] + ) + value *= factor + band["upper_cent"] = { + "numerator": value.numerator, + "denominator": value.denominator, + } + with pytest.raises(ValueError, match="exactly once"): + interval_table(twice) + for mutation in ("source_cut", "factor", "source_hash", "operation", "missing"): + tampered = copy.deepcopy(effective) + if mutation == "source_cut": + tampered["bands"][1]["source_upper_cent"] = 10_001 + elif mutation == "factor": + tampered["scaling"]["operational_factor"] = { + "numerator": 1117110, + "denominator": 1000000, + } + elif mutation == "source_hash": + tampered["scaling"]["source_table_sha256"] = "0" * 64 + elif mutation == "operation": + tampered["scaling"]["operation"] = "round_to_cents" + else: + tampered["bands"][1].pop("source_upper_cent") + with pytest.raises(ValueError): + interval_table(tampered) + + +def test_document_scaling_changes_only_named_tables(): + document = { + "schema_version": 1, + "tables": [_table(table_id="scaled"), _table(table_id="kept")], + } + effective = scale_interval_document( + document, + { + "scaled": { + "factor": CENTRAL, + "factor_id": "toy_factor", + "factor_declaration_sha256": "a" * 64, + "factor_receipt_sha256": "b" * 64, + } + }, + ) + assert effective["tables"][1] == document["tables"][1] + assert "scaling" in effective["tables"][0] + assert interval_document_sha256(effective) != interval_document_sha256(document) + with pytest.raises(ValueError, match="Unknown interval tables"): + scale_interval_document(document, {"missing": {}}) + + +def test_input_fingerprints_keep_value_types(): + digests = { + interval_input_fingerprint(values) + for values in ([1, 2], [True, 2], [1.0, 2], ["1", 2], [np.int64(1), 2]) + } + assert len(digests) == 4 + assert interval_input_fingerprint([np.int64(1), 2]) == interval_input_fingerprint( + [1, 2] + ) + + +# --------------------------------------------------------------------------- +# Diagnostics on frames +# --------------------------------------------------------------------------- + + +def test_household_entity_table_is_weighted_through_memberships(): + table = interval_table( + _table(entity="household", income="household_income", universe="household_in") + ) + frame = Frame( + { + "person": pd.DataFrame( + {"person_id": [0, 1, 2, 3], "person_household_id": [0, 0, 1, 2]} + ), + "household": pd.DataFrame( + { + "household_id": [0, 1, 2], + "household_income": [0, 10_000, 10_001], + "household_in": ["included", "included", "excluded"], + } + ), + }, + EntitySchema(group_entities=("household",)), + {"person": Weights(np.asarray([2.0, 2.0, 3.0, 5.0]), WeightKind.CALIBRATED)}, + ) + report = frame_boundary_diagnostics(table, frame) + assert report["entity"] == "household" + assert report["weight_kind"] == "calibrated" + bands = {row["band"]: row for row in report["bands"]} + assert bands["nil"]["declared"]["weighted_count"] == { + "numerator": 2, + "denominator": 1, + } + assert bands["b0"]["declared"]["weighted_count"] == { + "numerator": 3, + "denominator": 1, + } + assert report["included_records"] == 2 + # The left-closed alternative moves the exact-cut household to the next band. + assert bands["b0"]["delta"]["weighted_count"] == { + "numerator": -3, + "denominator": 1, + } + assert bands["b1"]["delta"]["weighted_amount_cents"] == { + "numerator": 30_000, + "denominator": 1, + } + + +def test_group_entity_without_weights_resolves_from_the_weighted_household(): + table = interval_table( + _table(entity="tax_unit", income="unit_income", universe="unit_in") + ) + frame = Frame( + { + "person": pd.DataFrame( + { + "person_id": [0, 1, 2], + "person_household_id": [0, 0, 1], + "person_tax_unit_id": [0, 1, 2], + } + ), + "household": pd.DataFrame({"household_id": [0, 1]}), + "tax_unit": pd.DataFrame( + { + "tax_unit_id": [0, 1, 2], + "unit_income": [5, 0, 200_000], + "unit_in": ["included", "excluded", "included"], + } + ), + }, + EntitySchema(group_entities=("household", "tax_unit")), + {"household": Weights(np.asarray([4.0, 6.0]), WeightKind.DESIGN)}, + ) + report = frame_boundary_diagnostics(table, frame) + bands = {row["band"]: row for row in report["bands"]} + assert bands["b0"]["declared"]["weighted_count"]["numerator"] == 4 + assert bands["b2"]["declared"]["weighted_amount_cents"]["numerator"] == 1_200_000 + assert report["weight_kind"] == "design" + + +def test_diagnostics_report_near_cut_mass_digests_and_disclosure(): + effective = interval_table(_scale(_table())) + amounts = [0, 11_071, 11_072, 11_271, 11_272, 111_711] + weights = [1.0, 0.5, 0.25, 0.125, 2.0, 3.0] + report = boundary_diagnostics( + effective, + list(range(6)), + amounts, + ["included"] * 6, + weights, + weight_record_ids=list(range(6)), + weight_kind="design", + ) + near = {row["cut"]: row for row in report["cuts"]} + # |z - 11,171.09| <= 100 cents admits 11,072 and 11,271 only. + assert near["b0"]["near_cut_records"] == 2 + assert Fraction(**near["b0"]["near_cut_weighted_count"]) == Fraction(3, 8) + assert near["b0"]["cut_cents"] == {"numerator": 1117109, "denominator": 100} + assert near["b0"]["source_cut_cents"] == 10_000 + assert near["first_lower_cut"]["near_cut_records"] == 1 + assert report["publisher_reclassification"] == "unavailable" + assert "cannot be recovered" in report["limitation"] + assert report["digests"]["factor"]["operational_factor"] == CENTRAL + assert set(report["digests"]) == { + "table_sha256", + "source_cuts_sha256", + "effective_cuts_sha256", + "factor", + "weights_sha256", + "record_order_sha256", + } + assert ( + report["digests"]["source_cuts_sha256"] + != report["digests"]["effective_cuts_sha256"] + ) + + +def test_misaligned_weights_and_nonfinite_weights_refuse(): + table = interval_table(_table()) + arguments = dict( + record_ids=[0, 1], + amounts=[1, 2], + universe=["included", "included"], + weight_kind="design", + ) + with pytest.raises(ValueError, match="aligned"): + boundary_diagnostics( + table, weights=[1.0, 2.0], weight_record_ids=[1, 0], **arguments + ) + with pytest.raises(ValueError, match="finite"): + boundary_diagnostics( + table, weights=[1.0, float("nan")], weight_record_ids=[0, 1], **arguments + ) + + +# --------------------------------------------------------------------------- +# Hypothesis: an independent Fraction oracle +# --------------------------------------------------------------------------- + + +def _oracle_cut(value) -> Fraction: + if isinstance(value, dict): + return Fraction(value["numerator"], value["denominator"]) + return Fraction(value) + + +def _oracle_cuts(table) -> list[Fraction]: + cuts = [_oracle_cut(table["first_lower_cut_cents"])] + for band in table["bands"]: + if band["kind"] == "positive" and band["upper_cent"] is not None: + cuts.append(_oracle_cut(band["upper_cent"])) + return cuts + + +def _oracle_band(z: Fraction, table) -> str: + """Band id for a nonnegative income under the table's own declaration.""" + if table["nil_band"] == "present" and z == 0: + return "nil" + cuts = _oracle_cuts(table) + positive = [band["id"] for band in table["bands"] if band["kind"] == "positive"] + for index, band_id in enumerate(positive): + lower = cuts[index] + upper = cuts[index + 1] if index + 1 < len(cuts) else None + if table["positive_band_closure"] == "right": + inside = lower < z and (upper is None or z <= upper) + else: + inside = lower <= z and (upper is None or z < upper) + if inside: + return band_id + return "below" + + +@st.composite +def _tables(draw, big=False): + count = draw(st.integers(min_value=1, max_value=6)) + step = st.integers(min_value=1, max_value=10**30 if big else 50_000) + closure = draw(st.sampled_from(["left", "right"])) + nil = draw(st.booleans()) + first = draw(st.one_of(st.just(0), step)) + cuts, previous = [], first + for _ in range(count): + previous += draw(step) + cuts.append(previous) + return _table( + tuple(cuts), + closure=closure, + nil=nil, + first=first, + ) + + +_FACTORS = st.builds( + lambda numerator, denominator: { + "numerator": numerator, + "denominator": denominator, + }, + st.integers(min_value=1, max_value=10**9), + st.one_of( + st.sampled_from([1, 10, 100, 1_000_000]), + st.integers(min_value=1, max_value=10**9), + ), +) + + +def _near_cuts(table, draw, count): + cuts = [int(cut) for cut in _oracle_cuts(table)] + values = st.one_of( + st.integers(min_value=-(10**6), max_value=cuts[-1] * 2 + 10), + st.sampled_from(cuts).flatmap( + lambda cut: st.integers(min_value=cut - 2, max_value=cut + 2) + ), + ) + return draw(st.lists(values, min_size=1, max_size=count)) + + +@given(data=st.data()) +@_SETTINGS +def test_property_included_records_fall_in_exactly_one_band_excluded_in_none(data): + table = data.draw(_tables()) + amounts = _near_cuts(table, data.draw, 24) + universe = data.draw( + st.lists( + st.sampled_from(["included", "excluded"]), + min_size=len(amounts), + max_size=len(amounts), + ) + ) + parsed = interval_table(table) + indicators = interval_indicators(parsed, amounts, universe) + stacked = np.vstack(list(indicators.values())) + for index, (amount, status) in enumerate(zip(amounts, universe, strict=True)): + column = stacked[:, index] + expected = _oracle_band(Fraction(max(0, amount)), table) + if status == "excluded": + assert not column.any() + elif expected == "below": + assert not column.any() + assert _oracle_cuts(table)[0] > 0 or ( + table["nil_band"] == "absent" + and table["positive_band_closure"] == "right" + and amount <= 0 + ) + else: + assert column.sum() == 1 + assert parsed.band_ids[int(np.argmax(column))] == expected + + +@given(data=st.data()) +@_SETTINGS +def test_property_unresolved_records_never_yield_indicators(data): + table = data.draw(_tables()) + amounts = _near_cuts(table, data.draw, 12) + universe = data.draw( + st.lists( + st.sampled_from(["included", "excluded", "unresolved"]), + min_size=len(amounts), + max_size=len(amounts), + ) + ) + unresolved = universe.count("unresolved") + if not unresolved: + universe[data.draw(st.integers(0, len(universe) - 1))] = "unresolved" + unresolved = 1 + with pytest.raises(IntervalPreparationError) as refused: + interval_indicators(interval_table(table), amounts, universe) + assert refused.value.summary["reasons"]["unresolved_universe_status"] == unresolved + + +@given(table=_tables(), factor=_FACTORS) +@_SETTINGS +def test_property_scaling_preserves_order_nil_closure_and_tails(table, factor): + effective = _scale(table, factor) + rational = Fraction(factor["numerator"], factor["denominator"]) + assert [_oracle_cut(cut) for cut in [effective["first_lower_cut_cents"]]] == [ + Fraction(table["first_lower_cut_cents"]) * rational + ] + assert _oracle_cuts(effective) == [cut * rational for cut in _oracle_cuts(table)] + cuts = _oracle_cuts(effective) + assert all(left < right for left, right in zip(cuts, cuts[1:], strict=False)) + for before, after in zip(table["bands"], effective["bands"], strict=True): + assert (before["id"], before["kind"], before["indicator"]) == ( + after["id"], + after["kind"], + after["indicator"], + ) + assert effective["bands"][-1]["upper_cent"] is None + for key in ("positive_band_closure", "nil_band", "negative_income_policy"): + assert effective[key] == table[key] + with pytest.raises(ValueError, match="already scaled"): + _scale(effective, factor) + + +@given(data=st.data(), factor=_FACTORS) +@_SETTINGS +def test_property_scaled_classification_equals_deflated_source_classification( + data, factor +): + table = data.draw(_tables()) + effective = _scale(table, factor) + rational = Fraction(factor["numerator"], factor["denominator"]) + scaled_cuts = _oracle_cuts(effective) + amounts = data.draw( + st.lists( + st.one_of( + st.integers(min_value=-(10**6), max_value=int(scaled_cuts[-1]) * 2 + 2), + st.sampled_from(scaled_cuts).flatmap( + lambda cut: st.integers( + min_value=int(cut) - 2, max_value=int(cut) + 2 + ) + ), + ), + min_size=1, + max_size=24, + ) + ) + actual = _classify(effective, amounts) + expected = [ + _oracle_band(Fraction(max(0, amount)) / rational, table) for amount in amounts + ] + assert actual == expected + + +@given(table=_tables(), factor=_FACTORS) +@_SETTINGS +def test_property_adjacent_attainable_cents_around_fractional_cuts(table, factor): + effective = _scale(table, factor) + for cut in _oracle_cuts(effective): + floor = cut.numerator // cut.denominator + amounts = [floor - 1, floor, floor + 1, floor + 2] + actual = _classify(effective, amounts) + assert actual == [ + _oracle_band(Fraction(max(0, amount)), effective) for amount in amounts + ] + if cut.denominator != 1: + # No attainable cent sits on a fractional cut: floor and floor + 1 + # straddle it under either closure. + assert floor < cut < floor + 1 + + +@given(data=st.data()) +@_SETTINGS +def test_property_permuting_records_and_weights_preserves_diagnostics(data): + table = data.draw(_tables()) + amounts = _near_cuts(table, data.draw, 16) + universe = data.draw( + st.lists( + st.sampled_from(["included", "excluded"]), + min_size=len(amounts), + max_size=len(amounts), + ) + ) + weights = data.draw( + st.lists( + st.floats(min_value=0, max_value=1e6, allow_nan=False), + min_size=len(amounts), + max_size=len(amounts), + ) + ) + ids = list(range(len(amounts))) + order = data.draw(st.permutations(ids)) + parsed = interval_table(table) + + def report(indices, weight_ids=None): + rows = [ids[index] for index in indices] + return boundary_diagnostics( + parsed, + rows, + [amounts[index] for index in indices], + [universe[index] for index in indices], + [weights[index] for index in indices], + weight_record_ids=rows if weight_ids is None else weight_ids, + weight_kind="design", + ) + + original, permuted = report(ids), report(order) + for key in ( + "cuts", + "bands", + "below_first_cut", + "floored_negative_income", + "included_records", + ): + assert original[key] == permuted[key] + if order != ids: + with pytest.raises(ValueError, match="aligned"): + report(order, weight_ids=ids) + + +@given(data=st.data()) +@_SETTINGS +def test_property_alternative_closure_deltas_sum_to_zero_and_nil_is_unchanged(data): + table = data.draw(_tables()) + amounts = _near_cuts(table, data.draw, 20) + weights = data.draw( + st.lists( + st.floats(min_value=0, max_value=1e9, allow_nan=False), + min_size=len(amounts), + max_size=len(amounts), + ) + ) + ids = list(range(len(amounts))) + report = boundary_diagnostics( + interval_table(table), + ids, + amounts, + ["included"] * len(amounts), + weights, + weight_record_ids=ids, + weight_kind="design", + ) + rows = [row for row in report["bands"] if row["kind"] == "positive"] + rows.append(report["below_first_cut"]) + for measure in ("weighted_count", "weighted_amount_cents"): + assert sum(Fraction(**row["delta"][measure]) for row in rows) == 0 + assert sum(row["delta"]["records"] for row in rows) == 0 + nil = [row for row in report["bands"] if row["kind"] == "nil"] + assert all(set(row) == {"band", "kind", "declared"} for row in nil) + # The oracle's exact weighted count per declared band. + for row in report["bands"]: + expected = sum( + ( + Fraction(weight) + for amount, weight in zip(amounts, weights, strict=True) + if _oracle_band(Fraction(max(0, amount)), table) == row["band"] + ), + Fraction(0), + ) + assert Fraction(**row["declared"]["weighted_count"]) == expected + + +@given(data=st.data()) +@_SETTINGS +def test_property_very_large_cross_products_do_not_overflow(data): + table = data.draw(_tables(big=True)) + factor = data.draw( + st.builds( + lambda numerator, denominator: { + "numerator": numerator, + "denominator": denominator, + }, + st.integers(min_value=1, max_value=10**40), + st.integers(min_value=1, max_value=10**40), + ) + ) + effective = _scale(table, factor) + cuts = _oracle_cuts(effective) + amounts = data.draw( + st.lists( + st.one_of( + st.integers(min_value=-(10**45), max_value=10**75), + st.sampled_from(cuts).flatmap( + lambda cut: st.integers( + min_value=int(cut) - 1, max_value=int(cut) + 1 + ) + ), + ), + min_size=1, + max_size=12, + ) + ) + rational = Fraction(factor["numerator"], factor["denominator"]) + assert _classify(effective, amounts) == [ + _oracle_band(Fraction(max(0, amount)) / rational, table) for amount in amounts + ] diff --git a/packages/microcosm-build/tests/engine_free/shared/test_reference_profiles.py b/packages/microcosm-build/tests/engine_free/shared/test_reference_profiles.py index c7324e58d7..62bb746fd6 100644 --- a/packages/microcosm-build/tests/engine_free/shared/test_reference_profiles.py +++ b/packages/microcosm-build/tests/engine_free/shared/test_reference_profiles.py @@ -3,15 +3,26 @@ from __future__ import annotations import copy +import json +from datetime import date import pytest +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st +from microcosm.build.reference_factors import resolve_reference_factor from microcosm.build.reference_profiles import ( REFERENCE_DOCUMENT_KEYS, reference_document_sha256, resolve_reference_profiles, validate_reference_resolution, ) +from microcosm.graph.canonical import canonical_json +from test_support.microcosm_build.reference_factors import ( + factor_context_fixture, + factor_fixture, +) +from test_support.paths import paths_for def _selector(key, category=None): @@ -291,3 +302,1075 @@ def test_effective_document_projects_resource_headers_and_binds_full_base(): effective ) assert validate_reference_resolution(effective, receipt) == receipt + + +def _scaling_inputs(pair_count=2, anchor_level="110"): + context, _, _ = factor_context_fixture(anchor_level=anchor_level) + references = {"country": "toy", "target_references": []} + money, counts = [], [] + for kind, names in (("count", counts), ("money", money)): + for index in range(pair_count): + name = f"{kind}_{index}" + names.append(name) + selector = _selector(f"{kind}-fact-{index}", index) + selector.update( + source_measure_id=kind, + source_concept=f"households.{kind}", + period_value=2001, + ) + row = { + "name": name, + "entity": "household", + "measure": f"prepared_{kind}", + "filter": f"band_{index}", + "period": 2002, + "ledger_selector": selector, + "metadata": { + "activation_status": "requires_prerequisites", + "reference_value_kind": kind, + "required_reference_profile": "aging_index", + "required_measurement_binding": "reviewed_income", + "reference_prerequisites": json.dumps( + ["reference_profile:aging_index", "measurement:reviewed_income"] + ), + "parking_reason": "Reviewed measurement remains unavailable.", + }, + } + if kind == "count": + row.update(value_operation="identity", value_operands=[]) + references["target_references"].append(row) + transformation = { + "operation": "scale_money_and_intervals", + "factor_id": "toy_factor", + "reference_names": money, + "count_reference_names": counts, + "interval_table_ids": [], + "required_measurement_binding": "reviewed_income", + } + declarations = { + "schema_version": 1, + "dimensions": { + "aging_index": { + "default": "central", + "profiles": { + name: {"transformations": [copy.deepcopy(transformation)]} + for name in ("low", "central", "high") + }, + } + }, + } + return references, declarations, context + + +def test_factor_scales_money_once_keeps_counts_and_measurement_prerequisite(): + references, declarations, context = _scaling_inputs() + original = copy.deepcopy((references, declarations, context)) + effective, _, receipt = resolve_reference_profiles( + references, declarations, {}, factor_context=context + ) + assert (references, declarations, context) == original + assert receipt["resolver_version"] == "reference-profiles-v2" + assert set(receipt["selected_factors"]) == {"toy_factor"} + for source, row in zip( + references["target_references"], effective["target_references"], strict=True + ): + metadata = row["metadata"] + assert metadata["activation_status"] == "requires_prerequisites" + assert metadata["parking_reason"] == source["metadata"]["parking_reason"] + assert json.loads(metadata["reference_prerequisites_remaining"]) == [ + "measurement:reviewed_income" + ] + assert row["ledger_selector"] == source["ledger_selector"] + if row["measure"] == "prepared_count": + assert {key: value for key, value in row.items() if key != "metadata"} == { + key: value for key, value in source.items() if key != "metadata" + } + assert receipt["transformations"][row["name"]]["operation"] == "identity" + else: + assert row["value_operation"] == "linear_combination" + assert row["value_operands"] == [ + { + "aggregate_fact_key": source["ledger_selector"][ + "aggregate_fact_key" + ], + "expected_member_count": 1, + "weight": 1.1, + } + ] + assert validate_reference_resolution(effective, receipt) == receipt + with pytest.raises(ValueError, match="already been resolved"): + resolve_reference_profiles(effective, declarations, {}, factor_context=context) + + +@given( + pair_count=st.integers(min_value=1, max_value=16), + anchor=st.integers(min_value=1, max_value=500), +) +# Two integers are cheap to draw; a 31 s draw under host load tripped +# too_slow in review, so only wall-clock health is suppressed. +@settings( + max_examples=16, + database=None, + deadline=None, + suppress_health_check=[HealthCheck.too_slow], +) +def test_counts_are_invariant_and_every_money_row_uses_one_common_factor( + pair_count, anchor +): + references, declarations, context = _scaling_inputs(pair_count, str(anchor)) + effective, _, _ = resolve_reference_profiles( + references, declarations, {}, factor_context=context + ) + counts = references["target_references"][:pair_count] + effective_counts = effective["target_references"][:pair_count] + for before, after in zip(counts, effective_counts, strict=True): + assert before["ledger_selector"] == after["ledger_selector"] + assert before["value_operation"] == after["value_operation"] + assert before["value_operands"] == after["value_operands"] + weights = [ + row["value_operands"] for row in effective["target_references"][pair_count:] + ] + assert all(len(operands) == 1 for operands in weights) + rational = context["factors"][0]["operational_factor"] + assert {operands[0]["weight"] for operands in weights} == { + rational["numerator"] / rational["denominator"] + } + with pytest.raises(ValueError, match="already been resolved"): + resolve_reference_profiles(effective, declarations, {}, factor_context=context) + + +@pytest.mark.parametrize( + "mutation", + [ + "missing_count", + "swapped_roles", + "missing_both", + "mismatched_filter", + "overlap", + "duplicate", + "duplicate_count", + "source_period", + "target_period", + "diagnostic_factor", + "money_already_scaled", + "arbitrary_parking", + "missing_prerequisites", + "wrong_measurement", + "override_prerequisites", + "override_measurement", + "missing_context", + "wrong_factor", + "wrong_receipt", + "wrong_profile_factor", + ], +) +def test_invalid_factor_profiles_and_companions_refuse(mutation): + references, declarations, context = _scaling_inputs() + transform = declarations["dimensions"]["aging_index"]["profiles"]["central"][ + "transformations" + ][0] + if mutation == "missing_count": + transform["count_reference_names"].pop() + elif mutation == "swapped_roles": + transform["count_reference_names"], transform["reference_names"] = ( + transform["reference_names"], + transform["count_reference_names"], + ) + elif mutation == "missing_both": + transform["count_reference_names"].pop() + transform["reference_names"].pop() + elif mutation == "mismatched_filter": + references["target_references"][0]["filter"] = "wrong_band" + elif mutation == "overlap": + declarations["dimensions"]["another"] = copy.deepcopy( + declarations["dimensions"]["aging_index"] + ) + elif mutation == "duplicate": + transform["reference_names"].append(transform["reference_names"][0]) + elif mutation == "duplicate_count": + transform["count_reference_names"].append(transform["count_reference_names"][0]) + elif mutation in {"source_period", "target_period"}: + key = "ledger_selector" if mutation == "source_period" else "period" + for row in references["target_references"]: + if key == "ledger_selector": + row[key]["period_value"] = 1999 + else: + row[key] = 1999 + elif mutation == "diagnostic_factor": + entry = context["factors"][0] + entry["declaration"]["purpose"] = "diagnostic" + from microcosm.build.reference_factors import factor_document_sha256 + + entry["receipt"]["declaration_sha256"] = factor_document_sha256( + entry["declaration"] + ) + body = { + key: value + for key, value in entry["receipt"].items() + if key != "receipt_sha256" + } + entry["receipt"]["receipt_sha256"] = factor_document_sha256(body) + elif mutation == "money_already_scaled": + row = references["target_references"][-1] + row["value_operation"] = "linear_combination" + row["value_operands"] = [ + { + "aggregate_fact_key": row["ledger_selector"]["aggregate_fact_key"], + "expected_member_count": 1, + "weight": 1.1, + } + ] + elif mutation == "arbitrary_parking": + references["target_references"][0]["metadata"]["activation_status"] = ( + "requires_arbitrary_evidence" + ) + elif mutation == "missing_prerequisites": + references["target_references"][0]["metadata"].pop("reference_prerequisites") + elif mutation == "wrong_measurement": + references["target_references"][0]["metadata"][ + "required_measurement_binding" + ] = "other" + elif mutation in {"override_prerequisites", "override_measurement"}: + key = ( + "reference_prerequisites" + if mutation == "override_prerequisites" + else "required_measurement_binding" + ) + transform["metadata"] = {key: "forged"} + elif mutation == "missing_context": + context = None + elif mutation == "wrong_factor": + context["factors"][0]["operational_factor"]["numerator"] += 1 + elif mutation == "wrong_receipt": + context["factors"][0]["receipt"]["receipt_sha256"] = "0" * 64 + elif mutation == "wrong_profile_factor": + transform["factor_id"] = "missing" + with pytest.raises(ValueError): + resolve_reference_profiles(references, declarations, {}, factor_context=context) + + +def _interval_document(pair_count=2, *, table_id="reviewed_table", companions=True): + bands = [] + for index in range(pair_count): + band = { + "id": f"band_{index}", + "kind": "positive", + "upper_cent": None if index == pair_count - 1 else 10_000 * (index + 1), + "indicator": f"band_{index}", + } + if companions: + band.update( + count_reference=f"count_{index}", amount_reference=f"money_{index}" + ) + bands.append(band) + return { + "schema_version": 1, + "tables": [ + { + "id": table_id, + "entity": "household", + "currency": "XTS", + "input_unit": "integer_cent", + "income_column": "household_income_cents", + "universe_column": "household_income_universe", + "source_period": 2001, + "target_period": 2002, + "positive_band_closure": "right", + "nil_band": "absent", + "negative_income_policy": "floor_zero", + "first_lower_cut_cents": 0, + "source_locator": "Toy!A1:A2", + "diagnostics": { + "boundary_window_cents": 100, + "alternative_positive_band_closure": "left", + }, + "bands": bands, + } + ], + } + + +def _interval_inputs(pair_count=2): + references, declarations, context = _scaling_inputs(pair_count) + for profile in declarations["dimensions"]["aging_index"]["profiles"].values(): + profile["transformations"][0]["interval_table_ids"] = ["reviewed_table"] + return references, declarations, context, _interval_document(pair_count) + + +def _effective_cuts(intervals, table_id="reviewed_table"): + from fractions import Fraction + + table = next(table for table in intervals["tables"] if table["id"] == table_id) + return [ + None + if band["upper_cent"] is None + else Fraction( + band["upper_cent"]["numerator"], band["upper_cent"]["denominator"] + ) + for band in table["bands"] + ] + + +def test_named_interval_tables_scale_once_with_their_money_factor(): + references, declarations, context, intervals = _interval_inputs(3) + original = copy.deepcopy((references, declarations, context, intervals)) + effective, effective_intervals, receipt = resolve_reference_profiles( + references, declarations, {}, intervals, factor_context=context + ) + assert (references, declarations, context, intervals) == original + rational = context["factors"][0]["operational_factor"] + factor = rational["numerator"] / rational["denominator"] + # One factor covers each money/cut triple. + money = [ + row + for row in effective["target_references"] + if row["name"] in {"money_0", "money_1", "money_2"} + ] + assert {row["value_operands"][0]["weight"] for row in money} == {factor} + assert _effective_cuts(effective_intervals) == [11_000, 22_000, None] + table = effective_intervals["tables"][0] + assert table["scaling"]["factor_id"] == "toy_factor" + assert table["scaling"]["operational_factor"] == rational + assert [band.get("source_upper_cent") for band in table["bands"]] == [ + 10_000, + 20_000, + None, + ] + assert receipt["base_intervals_sha256"] == reference_document_sha256(intervals) + assert receipt["effective_intervals_sha256"] == reference_document_sha256( + effective_intervals + ) + assert receipt["effective_intervals_sha256"] != receipt["base_intervals_sha256"] + assert receipt["interval_tables"]["reviewed_table"]["factor_id"] == "toy_factor" + assert receipt["interval_tables_sha256"] == reference_document_sha256( + receipt["interval_tables"] + ) + assert receipt["receipt_sha256"] not in json.dumps(effective_intervals) + for row in effective["target_references"]: + assert ( + row["metadata"]["effective_intervals_sha256"] + == (receipt["effective_intervals_sha256"]) + ) + if row["metadata"]["reference_value_kind"] == "count": + source = next( + item + for item in references["target_references"] + if item["name"] == row["name"] + ) + assert row["value_operation"] == source["value_operation"] + assert row["value_operands"] == source["value_operands"] + assert ( + validate_reference_resolution( + effective, receipt, interval_document=effective_intervals + ) + == receipt + ) + with pytest.raises(ValueError, match="interval document hash mismatch"): + validate_reference_resolution(effective, receipt, interval_document=intervals) + with pytest.raises(ValueError, match="already been resolved"): + resolve_reference_profiles( + effective, declarations, {}, effective_intervals, factor_context=context + ) + with pytest.raises(ValueError, match="cannot contain scaled tables"): + resolve_reference_profiles( + references, declarations, {}, effective_intervals, factor_context=context + ) + + +@pytest.mark.parametrize( + "mutation", + [ + "missing_document", + "unknown_table", + "duplicate_table_id", + "omitted_band", + "extra_band", + "cross_pair", + "swapped_roles", + "duplicate_reference", + "wrong_filter", + "wrong_entity", + "no_companions", + "source_period", + "target_period", + "second_transformation", + ], +) +def test_interval_companions_must_be_exactly_the_scaled_rosters(mutation): + references, declarations, context, intervals = _interval_inputs(3) + transform = declarations["dimensions"]["aging_index"]["profiles"]["central"][ + "transformations" + ][0] + table = intervals["tables"][0] + bands = table["bands"] + if mutation == "missing_document": + intervals = None + elif mutation == "unknown_table": + transform["interval_table_ids"] = ["missing_table"] + elif mutation == "duplicate_table_id": + transform["interval_table_ids"] = ["reviewed_table", "reviewed_table"] + elif mutation == "omitted_band": + bands.pop(1) + elif mutation == "extra_band": + bands.insert( + 2, + { + "id": "band_extra", + "kind": "positive", + "upper_cent": 30_000, + "indicator": "band_extra", + "count_reference": "other_count", + "amount_reference": "other_money", + }, + ) + elif mutation == "cross_pair": + bands[0]["amount_reference"], bands[1]["amount_reference"] = ( + bands[1]["amount_reference"], + bands[0]["amount_reference"], + ) + elif mutation == "swapped_roles": + bands[0]["amount_reference"], bands[0]["count_reference"] = ( + bands[0]["count_reference"], + bands[0]["amount_reference"], + ) + elif mutation == "duplicate_reference": + bands[1]["count_reference"] = bands[0]["count_reference"] + elif mutation == "wrong_filter": + bands[0]["indicator"] = "another_indicator" + elif mutation == "wrong_entity": + table["entity"] = "person" + elif mutation == "no_companions": + intervals = _interval_document(3, companions=False) + elif mutation in {"source_period", "target_period"}: + table[mutation] = 1999 + else: + declarations["dimensions"]["another"] = { + "default": "only", + "profiles": {"only": {"transformations": [copy.deepcopy(transform)]}}, + } + with pytest.raises(ValueError): + resolve_reference_profiles( + references, declarations, {}, intervals, factor_context=context + ) + + +def test_tables_without_companions_validate_but_profiles_do_not_scale_them(): + references, declarations, context, intervals = _interval_inputs(2) + unscaled = _interval_document(3, table_id="declared_only", companions=False)[ + "tables" + ][0] + for band in unscaled["bands"]: + band["indicator"] = f"declared_{band['indicator']}" + intervals["tables"].append(unscaled) + _, effective_intervals, receipt = resolve_reference_profiles( + references, declarations, {}, intervals, factor_context=context + ) + assert effective_intervals["tables"][1] == unscaled + assert set(receipt["interval_tables"]) == {"reviewed_table"} + + +def test_unnamed_interval_tables_pass_through_and_effective_equals_base(): + references, declarations, context = _scaling_inputs() + intervals = _interval_document(2) + _, effective_intervals, receipt = resolve_reference_profiles( + references, declarations, {}, intervals, factor_context=context + ) + assert effective_intervals == intervals + assert "interval_tables" not in receipt + assert receipt["effective_intervals_sha256"] == receipt["base_intervals_sha256"] + + +def test_interval_scaling_is_local_to_the_selected_profile(): + references, declarations, context, intervals = _interval_inputs(2) + declaration, facts, identity = factor_fixture(anchor_level="105") + declaration["id"] = "toy_low" + factor, factor_receipt = resolve_reference_factor(declaration, facts, identity) + context["factors"].append( + { + "declaration": declaration, + "operational_factor": factor, + "receipt": factor_receipt, + } + ) + profiles = declarations["dimensions"]["aging_index"]["profiles"] + profiles["low"]["transformations"][0]["factor_id"] = "toy_low" + low = resolve_reference_profiles( + references, + declarations, + {"aging_index": "low"}, + intervals, + factor_context=context, + ) + central = resolve_reference_profiles( + references, declarations, {}, intervals, factor_context=context + ) + assert _effective_cuts(low[1]) == [10_500, None] + assert _effective_cuts(central[1]) == [11_000, None] + profiles["high"]["notes"] = "edited unselected high declaration" + assert ( + resolve_reference_profiles( + references, + declarations, + {"aging_index": "low"}, + intervals, + factor_context=context, + ) + == low + ) + assert ( + resolve_reference_profiles( + references, declarations, {}, intervals, factor_context=context + ) + == central + ) + + +@pytest.mark.parametrize( + "mutation", + [ + "record_factor", + "record_profile", + "record_hash", + "drop_records", + "document_table", + "unscaled_document", + ], +) +def test_rehashed_interval_scaling_records_still_refuse(mutation): + references, declarations, context, intervals = _interval_inputs(2) + effective, effective_intervals, receipt = resolve_reference_profiles( + references, declarations, {}, intervals, factor_context=context + ) + receipt = copy.deepcopy(receipt) + document = copy.deepcopy(effective_intervals) + record = receipt["interval_tables"]["reviewed_table"] + if mutation == "record_factor": + record["operational_factor"] = {"numerator": 1, "denominator": 1} + receipt["interval_tables_sha256"] = reference_document_sha256( + receipt["interval_tables"] + ) + elif mutation == "record_profile": + record["profile"] = "high" + receipt["interval_tables_sha256"] = reference_document_sha256( + receipt["interval_tables"] + ) + elif mutation == "record_hash": + record["effective_table_sha256"] = "0" * 64 + elif mutation == "drop_records": + receipt.pop("interval_tables") + receipt.pop("interval_tables_sha256") + elif mutation == "document_table": + document["tables"][0]["scaling"]["factor_receipt_sha256"] = "0" * 64 + receipt["effective_intervals_sha256"] = reference_document_sha256(document) + else: + document = copy.deepcopy(intervals) + receipt["effective_intervals_sha256"] = reference_document_sha256(document) + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises(ValueError): + validate_reference_resolution(effective, receipt, interval_document=document) + + +def test_factor_evidence_and_unselected_profile_locality(): + references, declarations, context = _scaling_inputs() + low = resolve_reference_profiles( + references, declarations, {"aging_index": "low"}, factor_context=context + ) + central = resolve_reference_profiles( + references, declarations, {}, factor_context=context + ) + declarations["dimensions"]["aging_index"]["profiles"]["high"]["notes"] = ( + "edited unselected declaration" + ) + unselected = copy.deepcopy(context["factors"][0]) + unselected["declaration"]["id"] = "unselected_invalid_factor" + context["factors"].append(unselected) + assert ( + resolve_reference_profiles( + references, declarations, {"aging_index": "low"}, factor_context=context + ) + == low + ) + assert ( + resolve_reference_profiles(references, declarations, {}, factor_context=context) + == central + ) + # Factor evidence is part of selection identity, not merely an opaque attachment. + receipt = copy.deepcopy(central[2]) + receipt["selected_factor_identities"]["toy_factor"]["receipt_sha256"] = "0" * 64 + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises(ValueError, match="factor evidence identity"): + validate_reference_resolution(central[0], receipt) + + +def test_legacy_receipt_remains_version_one_without_factor_fields(): + references, declarations = _inputs() + _, _, receipt = resolve_reference_profiles(references, declarations, {}) + assert receipt["resolver_version"] == "reference-profiles-v1" + assert "selected_factors" not in receipt + assert "selected_factor_identities" not in receipt + assert "factor_companions" not in receipt + assert "factor_companions_sha256" not in receipt + # Canonical bytes produced by the v1 resolver at 1d5fff46. + assert reference_document_sha256(receipt) == ( + "753fe7ddb2bc5e00cc4d70a74e0cac8295af266ffbc05511101540e39ae21508" + ) + + +def test_legacy_receipt_without_transformed_names_refuses_as_a_value_error(): + references, declarations = _inputs() + effective, _, receipt = resolve_reference_profiles(references, declarations, {}) + receipt.pop("transformed_names") + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises(ValueError, match="transformed names"): + validate_reference_resolution(effective, receipt) + + +def test_unnamed_unresolved_rows_still_validate_without_factor_evidence(): + references, declarations = _inputs() + effective, _, receipt = resolve_reference_profiles(references, declarations, {}) + effective["target_references"].extend( + [ + {"entity": "household", "metadata": {}}, + {"entity": "household", "metadata": {}}, + ] + ) + receipt.pop("receipt_sha256") + receipt["effective_references_sha256"] = reference_document_sha256(effective) + receipt["receipt_sha256"] = reference_document_sha256(receipt) + assert validate_reference_resolution(effective, receipt) == receipt + + +def test_duplicate_unresolved_factor_companion_refuses(): + references, declarations, context = _scaling_inputs() + effective, _, receipt = resolve_reference_profiles( + references, declarations, {}, factor_context=context + ) + duplicate = copy.deepcopy(effective["target_references"][0]) + assert duplicate["name"] == "count_0" + duplicate["metadata"].pop("reference_profiles_resolved") + effective["target_references"].append(duplicate) + receipt["effective_references_sha256"] = reference_document_sha256(effective) + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises(ValueError, match="Duplicate factor companion"): + validate_reference_resolution(effective, receipt) + + +@pytest.mark.parametrize("with_factors", [False, True], ids=["v1", "v2"]) +@pytest.mark.parametrize( + "mutation", + [ + "transformations_list", + "transformations_null", + "transformation_scalar", + "resolved_name_missing", + "resolved_name_null", + "resolved_name_empty", + "resolved_name_scalar", + "resolved_name_list", + ], +) +def test_malformed_resolution_shapes_refuse_as_value_errors(with_factors, mutation): + if with_factors: + references, declarations, context = _scaling_inputs() + effective, _, receipt = resolve_reference_profiles( + references, declarations, {}, factor_context=context + ) + else: + references, declarations = _inputs() + effective, _, receipt = resolve_reference_profiles(references, declarations, {}) + row = effective["target_references"][0] + if mutation == "transformations_list": + receipt["transformations"] = [] + elif mutation == "transformations_null": + receipt["transformations"] = None + elif mutation == "transformation_scalar": + receipt["transformations"][row["name"]] = 7 + elif mutation == "resolved_name_missing": + row.pop("name") + else: + row["name"] = { + "resolved_name_null": None, + "resolved_name_empty": "", + "resolved_name_scalar": 7, + "resolved_name_list": [], + }[mutation] + receipt["effective_references_sha256"] = reference_document_sha256(effective) + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises(ValueError, match="transformations|reference names"): + validate_reference_resolution(effective, receipt) + + +@pytest.mark.parametrize( + "name_fields", + [{}, {"name": None}, {"name": ""}, {"name": 7}, {"name": []}], + ids=["missing", "null", "empty", "int", "list"], +) +def test_unnamed_unresolved_factor_rows_refuse_as_value_errors(name_fields): + references, declarations, context = _scaling_inputs() + effective, _, receipt = resolve_reference_profiles( + references, declarations, {}, factor_context=context + ) + effective["target_references"].append( + {"entity": "household", "metadata": {}, **name_fields} + ) + receipt["effective_references_sha256"] = reference_document_sha256(effective) + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises(ValueError, match="reference names"): + validate_reference_resolution(effective, receipt) + + +def test_nz_default_factor_receipt_is_compact_and_covers_the_exact_roster(): + spec = paths_for("microcosm-build").package / "src/microcosm/build/nz" + base = json.loads((spec / "target_references.json").read_text()) + declarations = json.loads((spec / "reference_profiles.json").read_text()) + context = json.loads((spec / "reference_aging.json").read_text()) + intervals = json.loads((spec / "reference_intervals.json").read_text()) + _, _, receipt = resolve_reference_profiles( + base, declarations, {}, intervals, factor_context=context + ) + assert set(receipt["interval_tables"]) == {"ird_taxable_income_national_ty2024"} + assert ( + receipt["interval_tables"]["ird_taxable_income_national_ty2024"]["bands"] == 237 + ) + assert "selected_declarations" not in receipt + assert "base_reference_document" not in receipt + companions = receipt["factor_companions"] + expected_names = { + f"ird_taxable_income_{kind}_by_band__row_{index}" + for kind in ("people", "total") + for index in range(8, 245) + } + assert len(companions) == 474 + assert set(companions) == expected_names + source_rows = {row["name"]: row for row in base["target_references"]} + for name, companion in companions.items(): + source = source_rows[name] + role = source["metadata"]["reference_value_kind"] + assert companion == { + "role": role, + "factor_id": "ird_ty2024_to_ty2027_central", + "dimension": "aging_index", + "profile": "central", + "source": { + "ledger_selector": source["ledger_selector"], + "period": source.get("period"), + "value_operation": source.get("value_operation", "identity"), + "value_operands": source.get("value_operands", []), + "metadata": {"reference_value_kind": role}, + }, + } + assert receipt["factor_companions_sha256"] == reference_document_sha256(companions) + assert len(canonical_json(receipt)) < 2_600_000 + + +def test_nz_default_factor_resolution_validates_after_declaration_expiry(monkeypatch): + from microcosm.build import reference_factors + + class LaterDate(date): + @classmethod + def today(cls): + return cls(2026, 11, 5) + + monkeypatch.setattr(reference_factors, "date", LaterDate) + spec = paths_for("microcosm-build").package / "src/microcosm/build/nz" + base = json.loads((spec / "target_references.json").read_text()) + declarations = json.loads((spec / "reference_profiles.json").read_text()) + context = json.loads((spec / "reference_aging.json").read_text()) + intervals = json.loads((spec / "reference_intervals.json").read_text()) + effective, effective_intervals, receipt = resolve_reference_profiles( + base, declarations, {}, intervals, factor_context=context + ) + assert receipt["selected_factors"] + assert ( + validate_reference_resolution( + effective, receipt, interval_document=effective_intervals + ) + == receipt + ) + + +def test_unrelated_direct_fact_references_are_outside_companion_rosters(): + references, declarations, context = _scaling_inputs() + direct = { + "name": "other_direct_fact", + "ledger_fact_key": "other", + "entity": "household", + } + references["target_references"].append(direct) + effective, _, _ = resolve_reference_profiles( + references, declarations, {}, factor_context=context + ) + assert effective["target_references"][-1] == direct + + +def test_self_consistent_effective_money_tampering_still_refuses(): + references, declarations, context = _scaling_inputs() + effective, _, receipt = resolve_reference_profiles( + references, declarations, {}, factor_context=context + ) + effective["target_references"][-1]["value_operands"][0]["weight"] *= 1.1 + receipt["effective_references_sha256"] = reference_document_sha256(effective) + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises(ValueError, match="must be applied exactly once"): + validate_reference_resolution(effective, receipt) + + +@pytest.mark.parametrize("target", ["count", "money"]) +def test_rehashed_factor_application_cannot_bypass_companion_role(target): + references, declarations, context = _scaling_inputs() + effective, _, receipt = resolve_reference_profiles( + references, declarations, {}, factor_context=context + ) + row = next( + row for row in effective["target_references"] if row["name"] == f"{target}_0" + ) + row["value_operation"] = "linear_combination" + row["value_operands"] = [ + { + "aggregate_fact_key": row["ledger_selector"]["aggregate_fact_key"], + "expected_member_count": 1, + "weight": 2, + } + ] + if target == "money": + receipt["transformations"][row["name"]]["operation"] = "identity" + receipt["effective_references_sha256"] = reference_document_sha256(effective) + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises(ValueError, match="roster role|count value semantics"): + validate_reference_resolution(effective, receipt) + + +def test_rehashed_action_label_cannot_change_money_into_a_count(): + references, declarations, context = _scaling_inputs() + effective, _, receipt = resolve_reference_profiles( + references, declarations, {}, factor_context=context + ) + row = next( + row for row in effective["target_references"] if row["name"] == "money_0" + ) + source = receipt["factor_companions"][row["name"]]["source"] + row["metadata"]["reference_value_kind"] = "count" + row["value_operation"] = source["value_operation"] + row["value_operands"] = copy.deepcopy(source["value_operands"]) + action = receipt["transformations"][row["name"]] + action["operation"] = "identity" + action["operand_selectors"] = copy.deepcopy(source["value_operands"]) + receipt["effective_references_sha256"] = reference_document_sha256(effective) + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises(ValueError, match="roster role"): + validate_reference_resolution(effective, receipt) + + +def test_count_preserves_original_weighted_operation_and_refuses_changed_weight(): + references, declarations, context = _scaling_inputs() + source = references["target_references"][0] + source["value_operation"] = "linear_combination" + source["value_operands"] = [ + { + "aggregate_fact_key": source["ledger_selector"]["aggregate_fact_key"], + "expected_member_count": 1, + "weight": 1, + } + ] + effective, _, receipt = resolve_reference_profiles( + references, declarations, {}, factor_context=context + ) + row = effective["target_references"][0] + assert row["value_operation"] == source["value_operation"] + assert row["value_operands"] == source["value_operands"] + assert row["metadata"]["reference_value_kind"] == "count" + action = receipt["transformations"][row["name"]] + assert action["operation"] == "identity" + assert action["operand_selectors"] == source["value_operands"] + assert validate_reference_resolution(effective, receipt) == receipt + + row["value_operands"][0]["weight"] = 2 + action["operand_selectors"][0]["weight"] = 2 + receipt["effective_references_sha256"] = reference_document_sha256(effective) + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises(ValueError, match="count value semantics"): + validate_reference_resolution(effective, receipt) + + +@pytest.mark.parametrize( + "mutation", + [ + "count_action", + "count_kind", + "outside_roster", + "outside_roster_without_factor", + "outside_roster_with_residual_label", + "source_values", + "roster", + ], +) +def test_factor_roles_and_count_semantics_use_hash_bound_companion_record(mutation): + references, declarations, context = _scaling_inputs() + effective, _, receipt = resolve_reference_profiles( + references, declarations, {}, factor_context=context + ) + row = effective["target_references"][0] + if mutation == "count_action": + receipt["transformations"][row["name"]]["operation"] = "linear_combination" + elif mutation == "count_kind": + row["metadata"]["reference_value_kind"] = "money" + elif mutation == "outside_roster": + previous = row["name"] + row["name"] = "unlisted_count" + receipt["transformations"][row["name"]] = receipt["transformations"].pop( + previous + ) + receipt["transformed_names"] = sorted(receipt["transformations"]) + elif mutation in { + "outside_roster_without_factor", + "outside_roster_with_residual_label", + }: + extra = copy.deepcopy(row) + extra["name"] = "unlisted_count" + effective["target_references"].append(extra) + receipt["transformations"][extra["name"]] = copy.deepcopy( + receipt["transformations"][row["name"]] + ) + receipt["transformations"][extra["name"]].pop("factor_id") + if mutation == "outside_roster_with_residual_label": + receipt["transformations"][extra["name"]]["operation"] = ( + "allocated_residual_by_ratio" + ) + receipt["transformed_names"] = sorted(receipt["transformations"]) + elif mutation == "source_values": + receipt["factor_companions"][row["name"]]["source"]["value_operands"] = [ + {"aggregate_fact_key": "count-fact-0", "weight": 2} + ] + elif mutation == "roster": + receipt["factor_companions"]["unlisted_count"] = receipt[ + "factor_companions" + ].pop(row["name"]) + receipt["effective_references_sha256"] = reference_document_sha256(effective) + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises( + ValueError, + match=( + "roster|companion.*hash|source.*identity|source semantics" + "|selection identity mismatch" + ), + ): + validate_reference_resolution(effective, receipt) + + +@pytest.mark.parametrize("target", ["money", "count"]) +def test_rehashed_forged_companion_role_requires_the_bound_selection_identity(target): + references, declarations, context = _scaling_inputs() + effective, _, receipt = resolve_reference_profiles( + references, declarations, {}, factor_context=context + ) + row = next( + row for row in effective["target_references"] if row["name"] == f"{target}_0" + ) + companion = receipt["factor_companions"][row["name"]] + forged_role = "count" if target == "money" else "money" + companion["role"] = forged_role + companion["source"]["metadata"]["reference_value_kind"] = forged_role + row["metadata"]["reference_value_kind"] = forged_role + action = receipt["transformations"][row["name"]] + if forged_role == "money": + rational = action["operational_factor"] + operation = "linear_combination" + operands = [ + { + "aggregate_fact_key": row["ledger_selector"]["aggregate_fact_key"], + "expected_member_count": 1, + "weight": rational["numerator"] / rational["denominator"], + } + ] + else: + operation = companion["source"]["value_operation"] + operands = companion["source"]["value_operands"] + row["value_operation"] = operation + row["value_operands"] = copy.deepcopy(operands) + action["operation"] = "linear_combination" if forged_role == "money" else "identity" + action["operand_selectors"] = copy.deepcopy(operands) + # Rehash every mutable attachment while retaining the original selection. + receipt["factor_companions_sha256"] = reference_document_sha256( + receipt["factor_companions"] + ) + receipt["effective_references_sha256"] = reference_document_sha256(effective) + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises(ValueError, match="selection identity mismatch"): + validate_reference_resolution(effective, receipt) + + +def test_factor_companion_hash_must_be_covered_by_the_selection_identity(): + references, declarations, context = _scaling_inputs() + effective, _, receipt = resolve_reference_profiles( + references, declarations, {}, factor_context=context + ) + incomplete_identity = { + key: receipt[key] + for key in ( + "resolver_version", + "base_references_sha256", + "base_intervals_sha256", + "selected_declarations_sha256", + "selection", + "selected_factor_identities", + "transformed_names", + ) + } + selection_hash = reference_document_sha256(incomplete_identity) + receipt["reference_selection_sha256"] = selection_hash + for row in effective["target_references"]: + row["metadata"]["reference_selection_sha256"] = selection_hash + receipt["effective_references_sha256"] = reference_document_sha256(effective) + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises(ValueError, match="selection identity mismatch"): + validate_reference_resolution(effective, receipt) + + +@pytest.mark.parametrize("mutation", ["missing_record", "untransformed_record"]) +def test_factor_companion_record_and_transformed_rows_cover_each_other(mutation): + references, declarations, context = _scaling_inputs() + effective, _, receipt = resolve_reference_profiles( + references, declarations, {}, factor_context=context + ) + companions = receipt["factor_companions"] + if mutation == "missing_record": + companions.pop("count_0") + else: + companions["untransformed_count"] = copy.deepcopy(companions["count_0"]) + receipt["factor_companions_sha256"] = reference_document_sha256(companions) + # Rebind the changed record so this checks roster coverage after identity. + identity = { + key: receipt[key] + for key in ( + "resolver_version", + "base_references_sha256", + "base_intervals_sha256", + "selected_declarations_sha256", + "selection", + "selected_factor_identities", + "factor_companions_sha256", + "transformed_names", + ) + } + selection_hash = reference_document_sha256(identity) + receipt["reference_selection_sha256"] = selection_hash + for row in effective["target_references"]: + row["metadata"]["reference_selection_sha256"] = selection_hash + receipt["effective_references_sha256"] = reference_document_sha256(effective) + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises(ValueError, match="roster|missing factor companion"): + validate_reference_resolution(effective, receipt) diff --git a/packages/microcosm-build/tests/engine_free/shared/test_spec_engine_country_bundles.py b/packages/microcosm-build/tests/engine_free/shared/test_spec_engine_country_bundles.py index 927db55d16..b9e2d872bb 100644 --- a/packages/microcosm-build/tests/engine_free/shared/test_spec_engine_country_bundles.py +++ b/packages/microcosm-build/tests/engine_free/shared/test_spec_engine_country_bundles.py @@ -234,6 +234,8 @@ def test_nz_generation_zero_views_come_from_the_country_spec_seam() -> None: "geography_spine.json", "holdout_references.json", "precal_references.json", + "reference_aging.json", + "reference_intervals.json", "reference_inventory.json", "reference_profiles.json", "release_contract.json", diff --git a/packages/microcosm-build/tests/engine_free/shared/test_transport_composed_graph.py b/packages/microcosm-build/tests/engine_free/shared/test_transport_composed_graph.py index 051e1c4cb7..e4df2e7599 100644 --- a/packages/microcosm-build/tests/engine_free/shared/test_transport_composed_graph.py +++ b/packages/microcosm-build/tests/engine_free/shared/test_transport_composed_graph.py @@ -43,16 +43,20 @@ import shutil import time from dataclasses import replace +from datetime import UTC, date, datetime, timedelta, timezone from pathlib import Path from unittest.mock import Mock import numpy as np +import pandas as pd import pytest from hypothesis import HealthCheck, given, settings from hypothesis import strategies as st +from microcosm.build.reference_profiles import reference_document_sha256 from microcosm.build.transport import cli as cli_module from microcosm.build.transport import compose as compose_module +from microcosm.build.transport import target_kernels as target_kernels_module from microcosm.build.transport.artifact_types import COMPARISON_TYPE from microcosm.build.transport.cli import ( EXPORT_FILENAME, @@ -70,6 +74,7 @@ ) from microcosm.build.transport.population_kernels import TRANSPORT_CURRENCY from microcosm.build.transport.takeup_kernels import GAP_TYPE +from microcosm.build.transport.target_kernels import CALIBRATION_PREPARE from microcosm.build.transport.terminal_kernels import materialize_export from microcosm.frame.kernels import SimulateRulesKernel from microcosm.graph import ( @@ -80,6 +85,7 @@ Determinism, GraphError, KernelBase, + KernelContext, KernelRegistry, Node, NodeRejectedError, @@ -94,6 +100,15 @@ from microcosm.graph.canonical import canonical_json from microcosm.graph.keys import node_key, source_content_key from test_support.microcosm_build.chronicle_feed import write_pinned_artifact +from test_support.microcosm_build.reference_factor_transport import ( + factor_transport_fixture, +) +from test_support.microcosm_build.reference_intervals import ( + INCOME_COLUMN, + UNIVERSE_COLUMN, + interval_bindings, + interval_profile_fixture, +) from test_support.microcosm_build.transport_composed import ( FAMILY_INPUTS, PROGRAMS, @@ -964,6 +979,304 @@ def test_preflight_checks_the_selected_variant_reference_status(composed): validate_transport_activation(spec) +def test_factor_context_is_read_without_composition_feed_io(tmp_path, monkeypatch): + _, pin, _, _, spec = factor_transport_fixture(tmp_path) + spec["resources"]["chronicle_feed"] = pin + + def no_feed_io(*args, **kwargs): + raise AssertionError("Composition must not load the consumer artifact.") + + monkeypatch.setattr( + "microcosm.build.ledger_artifact.load_ledger_consumer_artifact", no_feed_io + ) + view = compose_module.reference_profile_view(spec) + assert view[2]["selected_factors"]["toy_factor"]["operational_factor"] == { + "numerator": 1100000, + "denominator": 1000000, + } + assert all( + row["metadata"]["activation_status"] == "requires_prerequisites" + for row in view[0]["target_references"] + ) + assert compose_module.transport_resource(spec, "target_references") == view[0] + + +def test_factor_context_ignores_feed_pin_prose(tmp_path): + _, pin, _, _, spec = factor_transport_fixture(tmp_path) + spec["resources"]["chronicle_feed"] = pin + before = compose_module.reference_profile_view(spec) + pin["build"] = "Reviewed prose edit" + pin["source_repo"] = "Reviewed repository description" + assert compose_module.reference_profile_view(spec) == before + + +@pytest.mark.parametrize( + "defect", + ["missing", "wrong_feed", "wrong_commit", "wrong_manifest", "wrong_factor"], +) +def test_preflight_refuses_missing_or_incompatible_default_factor_context( + tmp_path, defect +): + _, pin, _, _, spec = factor_transport_fixture(tmp_path) + spec["resources"]["chronicle_feed"] = pin + if defect == "missing": + spec["resources"].pop("factor_context") + elif defect == "wrong_feed": + spec["resources"]["chronicle_feed"] = {**pin, "facts_sha256": "0" * 64} + elif defect == "wrong_commit": + pin["source_commit"] = "d" * 40 + elif defect == "wrong_manifest": + pin["manifest_sha256"] = "0" * 64 + else: + spec["resources"]["factor_context"]["factors"][0]["operational_factor"][ + "numerator" + ] += 1 + with pytest.raises( + ValueError, match="missing resource|incompatible|factor differs" + ): + validate_transport_activation(spec) + + +def test_preflight_resolves_empty_knobs_only_once(tmp_path, monkeypatch): + _, _, _, _, spec = factor_transport_fixture(tmp_path) + original = compose_module.reference_profile_view + selections = [] + + def recording_view(spec, selection=None): + selections.append(selection) + return original(spec, selection) + + monkeypatch.setattr(compose_module, "reference_profile_view", recording_view) + with pytest.raises(ValueError, match="Transport spec is not activated"): + validate_transport_activation(spec) + assert selections + assert all(selection is None for selection in selections) + + +def test_preflight_validates_scenario_factor_context_before_activation(tmp_path): + _, _, _, _, spec = factor_transport_fixture(tmp_path) + profiles = spec["resources"]["reference_profiles"]["dimensions"]["index"][ + "profiles" + ] + profiles["low"]["transformations"][0]["factor_id"] = "missing-scenario-factor" + assert compose_module.reference_profile_view(spec)[2]["selection"] == { + "index": "central" + } + spec["resources"]["scenarios"]["scenarios"].append( + {"id": "variant", "knobs": {"index": "low"}} + ) + with pytest.raises(ValueError, match="Missing selected factor"): + validate_transport_activation(spec) + + +def test_declared_ageing_scenarios_bind_selected_evidence_and_preserve_locality(): + spec = load_transport_spec("nz") + profiles = spec["resources"]["reference_profiles"] + receipts = {} + for scenario in spec["resources"]["scenarios"]["scenarios"]: + receipt = compose_module.reference_profile_view(spec, scenario["knobs"])[2] + receipts[scenario["id"]] = receipt + profile = {"V1": "low", "V2": "high"}.get(scenario["id"], "central") + factor_id = f"ird_ty2024_to_ty2027_{profile}" + assert receipt["selection"] == { + "aging_index": profile, + "census_residual_allocation": ( + "small_households" if scenario["id"] == "V4" else "mar" + ), + } + assert set(receipt["selected_factors"]) == {factor_id} + entry = next( + entry + for entry in spec["resources"]["reference_aging"]["factors"] + if entry["declaration"]["id"] == factor_id + ) + assert receipt["selected_factors"][factor_id] == entry + chosen = { + dimension: { + "name": name, + "declaration": profiles["dimensions"][dimension]["profiles"][name], + } + for dimension, name in receipt["selection"].items() + } + assert ( + receipt["selected_declarations_sha256"] + == hashlib.sha256(canonical_json(chosen)).hexdigest() + ) + profiles["dimensions"]["aging_index"]["profiles"]["high"]["notes"] = ( + "Reviewed edit confined to the unselected high profile." + ) + for scenario in spec["resources"]["scenarios"]["scenarios"]: + revised = compose_module.reference_profile_view(spec, scenario["knobs"])[2] + if scenario["id"] == "V2": + assert ( + revised["reference_selection_sha256"] + != receipts["V2"]["reference_selection_sha256"] + ) + else: + assert revised == receipts[scenario["id"]] + + +def _interval_prepare_spec(): + base, profiles, context, intervals = interval_profile_fixture() + table = intervals["tables"][0] + spec = { + "country": "xx", + "resources": { + "target_references": base, + "reference_profiles": profiles, + "factor_context": context, + "profile_intervals": intervals, + "calibration_bindings": interval_bindings(table), + }, + } + row = { + "id": "prepare", + "kernel": "calibration.prepare@1", + "population": "open", + "params": { + "bindings": {"resource": "calibration_bindings", "encoding": "json"}, + "references": {"resource": "target_references", "encoding": "json"}, + "references_sha256": { + "resource": "target_references", + "encoding": "sha256", + }, + }, + "outputs": [ + {"entity": "person", "column": band["indicator"], "dtype": "bool"} + for band in table["bands"] + ], + } + return spec, row + + +_INTERVAL_CONFIG = TransportGraphConfig( + engine_refs={}, create_outputs=(Owned("person", "age", "int64"),) +) + + +def _prepare_node(spec, row, knobs, *, interval_knobs="same"): + params = { + name: compose_module._resource_param(spec, value, profile_selection=knobs) + for name, value in row["params"].items() + } + if interval_knobs != "same": + params["intervals"] = compose_module._resource_param( + spec, + {"resource": "profile_intervals", "encoding": "json"}, + profile_selection=interval_knobs, + ) + return compose_module._node( + spec, + row, + _INTERVAL_CONFIG, + {}, + resolved_params=params, + profile_selection=knobs, + ) + + +def _run_prepare(node, incomes): + tables = { + "person": pd.DataFrame( + { + "person_id": range(len(incomes)), + INCOME_COLUMN: incomes, + UNIVERSE_COLUMN: ["included"] * len(incomes), + } + ) + } + return CALIBRATION_PREPARE.run( + KernelContext( + node=node, + tables=tables, + weights={}, + strata=pd.Series([], dtype=object, name="stratum"), + params=node.params, + rng=np.random.default_rng(0), + sources={}, + artifacts={}, + ) + ) + + +def test_composition_supplies_each_variant_its_own_effective_interval_companion(): + spec, row = _interval_prepare_spec() + incomes = [104_999, 107_000, 112_000, 114_000, 116_000] + first_band = {} + for profile, knobs in ( + ("central", None), + ("low", {"index": "low"}), + ("high", {"index": "high"}), + ): + node = _prepare_node(spec, row, knobs) + view = compose_module.reference_profile_view(spec, knobs) + assert node.params["intervals"] == canonical_json(view[1]).decode("utf-8") + assert json.loads(node.params["reference_resolution"]) == view[2] + result = _run_prepare(node, incomes) + first_band[profile] = result.columns["person", "toy_income_band_b0"].tolist() + evidence = json.loads(result.artifacts["preparation"]) + assert ( + evidence["effective_intervals_sha256"] + == view[2]["effective_intervals_sha256"] + ) + # 100,000 source cents become 105,000, 110,000 and 115,000: each variant + # regenerates its indicators from its own cuts rather than reusing S0's. + assert first_band == { + "low": [True, False, False, False, False], + "central": [True, True, False, False, False], + "high": [True, True, True, True, False], + } + + +def test_composition_refuses_a_supplied_interval_document_from_another_profile(): + spec, row = _interval_prepare_spec() + row = copy.deepcopy(row) + row["params"]["intervals"] = {"resource": "profile_intervals", "encoding": "json"} + node = _prepare_node(spec, row, {"index": "low"}) + assert ( + json.loads(node.params["intervals"])["tables"][0]["scaling"]["factor_id"] + == "toy_low" + ) + with pytest.raises(ValueError, match="differs from its effective interval"): + _prepare_node(spec, row, {"index": "low"}, interval_knobs=None) + + +def test_declared_scenarios_scale_national_cuts_with_their_own_factor(): + from fractions import Fraction + + spec = load_transport_spec("nz") + source = spec["resources"]["reference_intervals"] + by_id = {table["id"]: table for table in source["tables"]} + seen = {} + for scenario in spec["resources"]["scenarios"]["scenarios"]: + _, intervals, receipt = compose_module.reference_profile_view( + spec, scenario["knobs"] + ) + profile = {"V1": "low", "V2": "high"}.get(scenario["id"], "central") + tables = {table["id"]: table for table in intervals["tables"]} + national = tables["ird_taxable_income_national_ty2024"] + assert national["scaling"]["factor_id"] == f"ird_ty2024_to_ty2027_{profile}" + assert ( + tables["ird_taxable_income_age_ty2024"] + == by_id["ird_taxable_income_age_ty2024"] + ) + factor = national["scaling"]["operational_factor"] + rational = Fraction(factor["numerator"], factor["denominator"]) + for band, original in zip( + national["bands"], + by_id["ird_taxable_income_national_ty2024"]["bands"], + strict=True, + ): + if original.get("upper_cent") is not None: + upper = band["upper_cent"] + assert Fraction(upper["numerator"], upper["denominator"]) == ( + original["upper_cent"] * rational + ) + seen.setdefault(profile, set()).add(receipt["effective_intervals_sha256"]) + assert all(len(hashes) == 1 for hashes in seen.values()) + assert len(set().union(*seen.values())) == 3 + + class _IllegalOwner(KernelBase): ref = "test.illegal_owner@1" capabilities = Capabilities(Determinism.DETERMINISTIC) @@ -1314,7 +1627,10 @@ def test_packaged_spec_refuses_before_reading_any_source(tmp_path): ) -def test_cli_main_refuses_the_packaged_spec_and_writes_nothing(tmp_path, capsys): +def test_cli_main_refuses_the_packaged_spec_and_writes_nothing( + tmp_path, monkeypatch, capsys +): + monkeypatch.setattr(cli_module, "_today", lambda: date(2026, 10, 24)) out = tmp_path / "out" assert cli_module.main(["--country", "nz", "--out", str(out)]) == 1 message = capsys.readouterr().err @@ -1503,6 +1819,104 @@ def injected_registry(bindings, root, *, unit_rule, engines_by_binding=None): assert not (out / EXPORT_FILENAME).exists() +_AFTER_FACTOR_EXPIRY = date(2100, 1, 1) + + +@pytest.mark.parametrize("resume", ["auto", "forbid"]) +@pytest.mark.parametrize("selection", ["default", "scenario"]) +def test_cli_main_refuses_expired_factors_before_create( + tmp_path, monkeypatch, capsys, resume, selection +): + _, _, _, _, spec = factor_transport_fixture(tmp_path) + if selection == "scenario": + spec["resources"]["reference_profiles"]["dimensions"]["index"]["profiles"][ + "central" + ]["transformations"] = [] + spec["resources"]["scenarios"]["scenarios"].append( + {"id": "variant", "knobs": {"index": "low"}} + ) + monkeypatch.setattr(cli_module, "_today", lambda: _AFTER_FACTOR_EXPIRY) + monkeypatch.setattr(cli_module, "load_transport_spec", lambda source: spec) + later = _mock_steps_after_the_currency_check(monkeypatch) + out = tmp_path / "out" + assert ( + cli_module.main(["--country", "xx", "--out", str(out), "--resume", resume]) == 1 + ) + error = capsys.readouterr().err + assert "toy_factor" in error + assert "reviewed re-declaration" in error + for step in later: + step.assert_not_called() + assert not out.exists() + + +def _mock_steps_after_the_currency_check(monkeypatch): + """Activation, the registry, the CREATE inventory and CREATE, each refusing.""" + steps = [] + for owner, name in ( + (cli_module, "validate_transport_activation"), + (cli_module, "build_transport_registry"), + (cli_module, "prepare_create_outputs"), + (cli_module.TRANSPORT_CREATE, "run"), + ): + step = Mock(side_effect=AssertionError(f"Must refuse before {name}.")) + monkeypatch.setattr(owner, name, step) + steps.append(step) + return steps + + +@pytest.mark.parametrize("resume", ["auto", "forbid"]) +@pytest.mark.parametrize("selection", ["default", "scenario"]) +def test_preparation_refuses_expired_factors_for_library_callers( + tmp_path, monkeypatch, resume, selection +): + # prepare_transport_build is exported: a caller that skips main must meet + # the same run-entry check, before activation, the registry or CREATE. + _, _, _, _, spec = factor_transport_fixture(tmp_path) + if selection == "scenario": + spec["resources"]["reference_profiles"]["dimensions"]["index"]["profiles"][ + "central" + ]["transformations"] = [] + spec["resources"]["scenarios"]["scenarios"].append( + {"id": "variant", "knobs": {"index": "low"}} + ) + monkeypatch.setattr(cli_module, "_today", lambda: _AFTER_FACTOR_EXPIRY) + later = _mock_steps_after_the_currency_check(monkeypatch) + with pytest.raises(ValueError, match="toy_factor") as error: + cli_module.prepare_transport_build(spec, sources={}, resume=resume) + assert "reviewed re-declaration" in str(error.value) + for step in later: + step.assert_not_called() + + +def test_preparation_lets_require_reach_stored_work_after_expiry(tmp_path, monkeypatch): + # require skips the currency check and goes on to activation and the store. + _, _, _, _, spec = factor_transport_fixture(tmp_path) + monkeypatch.setattr(cli_module, "_today", lambda: _AFTER_FACTOR_EXPIRY) + reached = Mock(side_effect=LookupError("activation reached")) + monkeypatch.setattr(cli_module, "validate_transport_activation", reached) + with pytest.raises(LookupError, match="activation reached"): + cli_module.prepare_transport_build(spec, sources={}, resume="require") + reached.assert_called_once_with(spec) + + +def test_preparation_checks_resume_before_currency(tmp_path, monkeypatch): + _, _, _, _, spec = factor_transport_fixture(tmp_path) + monkeypatch.setattr(cli_module, "_today", lambda: _AFTER_FACTOR_EXPIRY) + with pytest.raises(ValueError, match="resume must be"): + cli_module.prepare_transport_build(spec, sources={}, resume="sometimes") + + +def test_cli_factor_currency_decision_allows_historical_replay(tmp_path, monkeypatch): + # The factor fixture has parked measurement rows and no runnable skeleton. + # Exercise the CLI decision directly; the warm-store test below verifies + # actual require execution with the engine-free composed skeleton. + _, _, _, _, spec = factor_transport_fixture(tmp_path) + assert compose_module.reference_profile_view(spec)[2]["selected_factors"] + monkeypatch.setattr(cli_module, "_today", lambda: _AFTER_FACTOR_EXPIRY) + cli_module._require_current_run_factors(spec, resume="require") + + def test_cli_main_and_path_loader_success(composed, tmp_path, monkeypatch, capsys): # Real Path loading, registry preparation and execution; only the injected # engine seam replaces Axiom with the fixture's pure-Python adapters. @@ -1551,9 +1965,199 @@ def counted(context, _run=run, _ref=ref): assert (out / EXPORT_FILENAME).is_file() assert json.loads((out / "manifest.json").read_bytes())["nodes"] observe_warm.append(True) + monkeypatch.setattr(cli_module, "_today", lambda: _AFTER_FACTOR_EXPIRY) + assert cli_module.main([*argv, "--resume", "require"]) == 0 + assert capsys.readouterr().err == "" + assert calls == [] + + +def test_cli_run_date_is_the_utc_date(monkeypatch): + # 11:30pm in New York on 3 November is already 4 November in UTC, where CI runs. + instant = datetime(2026, 11, 4, 3, 30, tzinfo=UTC) + + class Clock(datetime): + @classmethod + def now(cls, tz=None): + return instant.astimezone(tz or timezone(timedelta(hours=-5))) + + monkeypatch.setattr(cli_module, "datetime", Clock) + assert cli_module._today() == date(2026, 11, 4) + + +def test_cli_currency_check_walks_the_views_activation_walks(tmp_path, monkeypatch): + # Activation resolves scenario views only when both resources exist and + # validates their shapes; the run-entry check shares that walk. + _, _, _, _, spec = factor_transport_fixture(tmp_path) + del spec["resources"]["scenarios"] + assert len(compose_module.reference_profile_views(spec)) == 1 + monkeypatch.setattr(cli_module, "_today", lambda: date(2050, 1, 1)) + cli_module._require_current_run_factors(spec, resume="auto") + monkeypatch.setattr(cli_module, "_today", lambda: _AFTER_FACTOR_EXPIRY) + with pytest.raises(ValueError, match="toy_factor"): + cli_module._require_current_run_factors(spec, resume="auto") + spec["resources"]["scenarios"] = {"scenarios": {"id": "malformed"}} + with pytest.raises(TypeError) as activation: + compose_module.validate_transport_activation(spec) + with pytest.raises(TypeError) as run_entry: + cli_module._require_current_run_factors(spec, resume="auto") + assert str(run_entry.value) == str(activation.value) == "scenarios must be a list." + + +def test_cli_require_replays_a_warm_store_after_selected_factors_expire( + composed, tmp_path, monkeypatch, capsys +): + # End to end: warm a real store while a selected factor is current, then + # replay it past valid_until. require verifies and runs nothing; a new run + # of the same spec refuses on that factor before preparation work. + facts, pin, _, _, factors = factor_transport_fixture(tmp_path / "factor") + spec = copy.deepcopy(composed.spec) + spec["resources"].update( + factor_target_references=factors["resources"]["target_references"], + factor_context=factors["resources"]["factor_context"], + factor_feed=pin, + reference_profiles={ + **factors["resources"]["reference_profiles"], + "reference_resource": "factor_target_references", + }, + ) + profile_view = compose_module.reference_profile_view + + def measured_view(spec, selection=None): + # As in factor_transport_fixture(activate=True), supply a synthetic + # reviewed measurement closure. The real resolver still selects and + # binds the factors; composition must attach its rehashed receipt. + # Copies, so the resolver's own return values are never edited. + references, intervals, receipt = profile_view(spec, selection) + references, receipt = copy.deepcopy(references), copy.deepcopy(receipt) + for row in references["target_references"]: + row["metadata"]["activation_status"] = "active" + receipt["effective_references_sha256"] = reference_document_sha256(references) + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + return references, intervals, receipt + + monkeypatch.setattr(compose_module, "reference_profile_view", measured_view) + declaration = spec["resources"]["transport_graph"] + compiler_id = "nz.factor.targets.compile" + declaration["sources"].append( + { + **next( + source + for source in declaration["sources"] + if source["name"] == "nz_calibration_facts" + ), + "name": "factor_facts", + } + ) + declaration["nodes"].append( + { + "id": compiler_id, + "kernel": "targets.compile@1", + "population": "nz.open", + "sources": ["factor_facts"], + "params": { + "country": factors["country"], + "references": { + "resource": "factor_target_references", + "encoding": "json", + }, + "references_sha256": { + "resource": "factor_target_references", + "encoding": "sha256", + }, + "chronicle_feed_pin": {"resource": "factor_feed", "encoding": "json"}, + }, + } + ) + # This factor-bound compiler is an explicit CLI terminal endpoint, so its + # target surface must actually be compiled and cached during the warm run. + declaration["endpoints"]["terminal"].append(compiler_id) + compiler = compose_transport_graph(spec, composed.config).node(compiler_id) + assert compiler.kernel == "targets.compile@1" + assert "reference_resolution" in compiler.params + resolution = json.loads(compiler.params["reference_resolution"]) + assert resolution["selected_factors"] + assert json.loads(compiler.params["chronicle_feed_pin"]) == pin + directory = _write_local_transport_spec(tmp_path / "spec", spec) + build_registry = cli_module.build_transport_registry + calls = [] + replay = Mock( + wraps=target_kernels_module.reference_factors_module.replay_reference_factor + ) + monkeypatch.setattr( + target_kernels_module.reference_factors_module, + "replay_reference_factor", + replay, + ) + + def injected_registry(bindings, root, *, unit_rule, engines_by_binding=None): + registry = build_registry( + bindings, + root, + unit_rule=unit_rule, + engines_by_binding=composed.engines_by_binding, + ) + for ref in registry.kernels.refs(): + kernel = registry.kernels.get(ref) + run = kernel.run + + def counted(context, _run=run): + calls.append(context.node.id) + return _run(context) + + monkeypatch.setattr(kernel, "run", counted) + return registry + + monkeypatch.setattr(cli_module, "build_transport_registry", injected_registry) + out = tmp_path / "out" + argv = ["--spec-dir", str(directory), "--out", str(out)] + for name, path in {**composed.sources, "factor_facts": facts}.items(): + argv.extend(["--source", f"{name}={path}"]) + monkeypatch.setattr(cli_module, "_today", lambda: date(2050, 1, 1)) + assert cli_module.main(argv) == 0 + assert capsys.readouterr().err == "" + assert calls.count(compiler_id) == 1 + replay.assert_called_once() + factor = resolution["selected_factors"]["toy_factor"] + # The replay ran against the authenticated factor feed: the facts an + # independent load of the pinned factor_facts source yields. + fed_facts = ( + target_kernels_module.ledger_artifact_module.load_ledger_consumer_artifact( + facts, feed_pin=pin, lexical_floats=True + ).facts + ) + assert fed_facts + replay.assert_called_once_with( + factor["declaration"], + fed_facts, + factor["declaration"]["feed_identity"], + factor["operational_factor"], + factor["receipt"], + ) + warm_node = json.loads((out / "manifest.json").read_bytes())["nodes"][compiler_id] + assert warm_node["receipt"]["n_targets"] == 2 + exported = (out / EXPORT_FILENAME).read_bytes() + calls.clear() + replay.reset_mock() + monkeypatch.setattr(cli_module, "_today", lambda: _AFTER_FACTOR_EXPIRY) assert cli_module.main([*argv, "--resume", "require"]) == 0 assert capsys.readouterr().err == "" + # require reads back the stored run's export and rewrites nothing. + assert (out / EXPORT_FILENAME).read_bytes() == exported + assert calls == [] + replay.assert_not_called() + stored_node = json.loads((out / "manifest.json").read_bytes())["nodes"][compiler_id] + assert stored_node["hit"] is True + assert stored_node["key"] == warm_node["key"] + assert stored_node["opaque_artifacts"] == warm_node["opaque_artifacts"] + later = _mock_steps_after_the_currency_check(monkeypatch) + assert cli_module.main([*argv, "--resume", "auto"]) == 1 + error = capsys.readouterr().err + assert "toy_factor" in error + assert "reviewed re-declaration" in error assert calls == [] + for step in later: + step.assert_not_called() def test_cli_main_invalid_arguments_are_a_refusal(capsys): diff --git a/packages/microcosm-build/tests/engine_free/shared/test_transport_target_kernels.py b/packages/microcosm-build/tests/engine_free/shared/test_transport_target_kernels.py index 9550f1ccaf..10c2d3c7df 100644 --- a/packages/microcosm-build/tests/engine_free/shared/test_transport_target_kernels.py +++ b/packages/microcosm-build/tests/engine_free/shared/test_transport_target_kernels.py @@ -20,7 +20,9 @@ from __future__ import annotations import json +from copy import deepcopy from dataclasses import replace +from pathlib import Path import numpy as np import pandas as pd @@ -28,6 +30,10 @@ from hypothesis import HealthCheck, given, settings from hypothesis import strategies as st +import microcosm.build.reference_factors as reference_factors_module +import microcosm.build.reference_intervals as reference_intervals_module +import microcosm.build.reference_profiles as reference_profiles_module +import microcosm.build.transport.target_kernels as target_kernels_module from microcosm.build.ledger_artifact import ChronicleFeedPinMismatchError from microcosm.build.reference_profiles import ( reference_document_sha256, @@ -62,6 +68,15 @@ ) from microcosm.graph.canonical import canonical_json from test_support.microcosm_build.chronicle_feed import write_pinned_artifact +from test_support.microcosm_build.reference_factor_transport import ( + factor_transport_fixture, +) +from test_support.microcosm_build.reference_intervals import ( + INCOME_COLUMN, + UNIVERSE_COLUMN, + interval_bindings, + interval_table_fixture, +) from test_support.microcosm_build.transport_graph import ( CALIBRATION_TARGETS, COUNTRY, @@ -167,6 +182,300 @@ def test_kernels_declare_honest_country_neutral_contracts() -> None: ) +@pytest.mark.parametrize( + "kernel", [TARGETS_COMPILE, TAKEUP_COMPARE], ids=lambda k: k.ref +) +def test_factor_verifier_source_changes_compilation_identity( + tmp_path, monkeypatch, kernel +): + before = kernel.implementation_hash() + source = Path(reference_factors_module.__file__) + changed = tmp_path / source.name + changed.write_bytes(source.read_bytes() + b"\n# verifier implementation mutation\n") + monkeypatch.setattr(reference_factors_module, "__file__", str(changed)) + assert kernel.implementation_hash() != before + + +def test_compiler_replays_factor_and_applies_one_common_money_weight(tmp_path): + path, pin, document, receipt, _ = factor_transport_fixture(tmp_path, activate=True) + payload, registry = compile_target_surface( + path, + document, + country=COUNTRY, + references_sha256=reference_document_sha256(document), + feed_pin=pin, + reference_resolution=receipt, + ) + assert registry.specs[0].value == 3 + assert registry.specs[1].value == pytest.approx(110) + assert decode_target_surface(payload).reference_resolution == receipt + + +def test_compile_replay_refuses_self_consistent_forged_factor(tmp_path): + path, pin, document, receipt, _ = factor_transport_fixture( + tmp_path, forged=True, activate=True + ) + # Composition has accepted all declaration/receipt hashes; only feed replay + # can distinguish this forged level from the authenticated source operand. + with pytest.raises(ValueError, match="expected factor mismatch"): + compile_target_surface( + path, + document, + country=COUNTRY, + references_sha256=reference_document_sha256(document), + feed_pin=pin, + reference_resolution=receipt, + ) + + +def test_compile_replays_correct_factor_without_pin_when_manifest_binds_commit( + tmp_path, +): + path, _, document, receipt, _ = factor_transport_fixture( + tmp_path, activate=True, manifest_commit=True + ) + _, registry = compile_target_surface( + path, + document, + country=COUNTRY, + references_sha256=reference_document_sha256(document), + reference_resolution=receipt, + ) + assert registry.specs[1].value == pytest.approx(110) + + +@pytest.mark.parametrize("manifest_commit", [False, True]) +def test_compile_without_pin_refuses_unauthenticated_or_different_feed( + tmp_path, manifest_commit +): + path, _, document, receipt, _ = factor_transport_fixture( + tmp_path, activate=True, manifest_commit=manifest_commit + ) + if manifest_commit: + # The declaration still has a valid receipt for its original artifact. + manifest_path = path / "manifest.json" + manifest = json.loads(manifest_path.read_text()) + manifest["source_commit"] = "d" * 40 + manifest_path.write_text(json.dumps(manifest)) + with pytest.raises(ValueError, match="cannot be authenticated|manifest_sha256"): + compile_target_surface( + path, + document, + country=COUNTRY, + references_sha256=reference_document_sha256(document), + reference_resolution=receipt, + ) + + +def test_compile_factor_ignores_pin_prose(tmp_path): + path, pin, document, receipt, _ = factor_transport_fixture(tmp_path, activate=True) + arguments = dict( + country=COUNTRY, + references_sha256=reference_document_sha256(document), + reference_resolution=receipt, + ) + before, _ = compile_target_surface(path, document, feed_pin=pin, **arguments) + after, _ = compile_target_surface( + path, document, feed_pin={**pin, "build": "Reviewed prose edit"}, **arguments + ) + assert before == after + + +@pytest.mark.parametrize("field", ["source_commit", "facts_sha256", "manifest_sha256"]) +def test_compile_factor_refuses_changed_pin_identity(tmp_path, field): + path, pin, document, receipt, _ = factor_transport_fixture(tmp_path, activate=True) + pin[field] = "d" * len(pin[field]) + with pytest.raises(ValueError, match="feed identity mismatch|pin mismatch"): + compile_target_surface( + path, + document, + country=COUNTRY, + references_sha256=reference_document_sha256(document), + feed_pin=pin, + reference_resolution=receipt, + ) + + +def test_compile_replay_refuses_tampered_evidence_with_recomputed_hashes(tmp_path): + path, pin, document, receipt, _ = factor_transport_fixture(tmp_path, activate=True) + factor_receipt = receipt["selected_factors"]["toy_factor"]["receipt"] + factor_receipt["source_schedule"][0]["decimal_operand"] = "99" + factor_receipt.pop("receipt_sha256") + factor_receipt["receipt_sha256"] = reference_document_sha256(factor_receipt) + receipt["selected_factor_identities"]["toy_factor"]["receipt_sha256"] = ( + factor_receipt["receipt_sha256"] + ) + receipt["reference_selection_sha256"] = reference_document_sha256( + reference_profiles_module._selection_identity(receipt) + ) + for row in document["target_references"]: + row["metadata"]["reference_selection_sha256"] = receipt[ + "reference_selection_sha256" + ] + receipt["effective_references_sha256"] = reference_document_sha256(document) + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises(ValueError, match="Factor replay differs"): + compile_target_surface( + path, + document, + country=COUNTRY, + references_sha256=reference_document_sha256(document), + feed_pin=pin, + reference_resolution=receipt, + ) + + +@pytest.mark.parametrize("target", ["count", "money"]) +def test_compile_replay_refuses_rehashed_factor_application_tampering(tmp_path, target): + path, pin, document, receipt, _ = factor_transport_fixture(tmp_path, activate=True) + row = next( + row for row in document["target_references"] if row["name"] == f"toy-{target}" + ) + row["value_operation"] = "linear_combination" + row["value_operands"] = [ + { + "aggregate_fact_key": row["ledger_selector"]["aggregate_fact_key"], + "expected_member_count": 1, + "weight": 2, + } + ] + if target == "money": + receipt["transformations"][row["name"]]["operation"] = "identity" + receipt["effective_references_sha256"] = reference_document_sha256(document) + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises(ValueError, match="roster role|count value semantics"): + compile_target_surface( + path, + document, + country=COUNTRY, + references_sha256=reference_document_sha256(document), + feed_pin=pin, + reference_resolution=receipt, + ) + + +@pytest.mark.parametrize("target", ["count", "money"]) +def test_compile_refuses_rehashed_companion_role_with_unchanged_selection( + tmp_path, target +): + path, pin, document, receipt, _ = factor_transport_fixture(tmp_path, activate=True) + name = f"toy-{target}" + companion = receipt["factor_companions"][name] + role = "count" if target == "money" else "money" + companion["role"] = role + companion["source"]["metadata"]["reference_value_kind"] = role + row = next(row for row in document["target_references"] if row["name"] == name) + action = receipt["transformations"][name] + # Make the forged role internally consistent. Its original selection hash + # must still refuse even when the action and effective row agree with it. + operation = "linear_combination" if role == "money" else "identity" + rational = action["operational_factor"] + operands = ( + [ + { + "aggregate_fact_key": row["ledger_selector"]["aggregate_fact_key"], + "expected_member_count": 1, + "weight": rational["numerator"] / rational["denominator"], + } + ] + if role == "money" + else [] + ) + row["metadata"]["reference_value_kind"] = role + row["value_operation"] = operation + row["value_operands"] = operands + action["operation"] = operation + action["operand_selectors"] = operands + receipt["factor_companions_sha256"] = reference_document_sha256( + receipt["factor_companions"] + ) + receipt["effective_references_sha256"] = reference_document_sha256(document) + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises(ValueError, match="Reference selection identity mismatch"): + compile_target_surface( + path, + document, + country=COUNTRY, + references_sha256=reference_document_sha256(document), + feed_pin=pin, + reference_resolution=receipt, + ) + + +def test_compile_refuses_outside_roster_row_with_residual_action(tmp_path): + path, pin, document, receipt, _ = factor_transport_fixture(tmp_path, activate=True) + extra = deepcopy(document["target_references"][0]) + previous = extra["name"] + extra["name"] = "unlisted-count" + document["target_references"].append(extra) + action = deepcopy(receipt["transformations"][previous]) + action.pop("factor_id") + action["operation"] = "allocated_residual_by_ratio" + receipt["transformations"][extra["name"]] = action + receipt["transformed_names"] = sorted(receipt["transformations"]) + receipt["effective_references_sha256"] = reference_document_sha256(document) + receipt.pop("receipt_sha256") + receipt["receipt_sha256"] = reference_document_sha256(receipt) + with pytest.raises( + ValueError, match="selection identity|outside its companion roster" + ): + compile_target_surface( + path, + document, + country=COUNTRY, + references_sha256=reference_document_sha256(document), + feed_pin=pin, + reference_resolution=receipt, + ) + + +@pytest.mark.parametrize( + "resolved", [False, True], ids=["unresolved", "legacy-resolution"] +) +def test_no_factor_compilation_is_identical_with_or_without_lexical_loading( + tmp_path, monkeypatch, resolved +): + facts = toy_facts(CALIBRATION_TARGETS) + path = write_facts(tmp_path / "facts.jsonl", facts) + document = references_for(CALIBRATION_TARGETS) + receipt = None + if resolved: + document, _, receipt = resolve_reference_profiles( + document, {"schema_version": 1, "dimensions": {}}, {} + ) + original_loader = target_kernels_module.load_ledger_consumer_artifact + requests = [] + outputs = [] + registries = [] + for force_lexical in (False, True): + + def load_with_selected_representation(*args, lexical=force_lexical, **kwargs): + requests.append(kwargs.get("lexical_floats", False)) + kwargs["lexical_floats"] = lexical + return original_loader(*args, **kwargs) + + monkeypatch.setattr( + target_kernels_module, + "load_ledger_consumer_artifact", + load_with_selected_representation, + ) + payload, registry = compile_target_surface( + path, + document, + country=COUNTRY, + references_sha256=reference_document_sha256(document), + reference_resolution=receipt, + ) + outputs.append(payload) + registries.append([spec.value for spec in registry.specs]) + assert requests == [False, False] + assert outputs[0] == outputs[1] + assert registries[0] == registries[1] + + def test_compile_emits_a_traced_surface_bound_to_facts_not_paths(tmp_path) -> None: payload = _surface(tmp_path) surface = decode_target_surface(payload) @@ -582,10 +891,15 @@ def test_surface_decode_refuses_a_tampered_trace_or_registry(tmp_path) -> None: ) +# Base/current seeded draws have identical inputs and measured generation cost. +# Host contention can exceed Hypothesis' wall-clock generation health check. @settings( max_examples=40, deadline=None, - suppress_health_check=(HealthCheck.function_scoped_fixture,), + suppress_health_check=( + HealthCheck.function_scoped_fixture, + HealthCheck.too_slow, + ), ) @given( chosen=st.lists( @@ -802,3 +1116,257 @@ def test_property_comparison_reports_the_fact_and_the_weighted_model( assert row["reference"] == row["name"] == HOLDOUT_TARGETS[0][0] assert document["weight_kind"] == "calibrated" assert result.receipt["n_comparisons"] == 1 + + +# --------------------------------------------------------------------------- +# Interval preparation and pre-fit boundary diagnostics +# --------------------------------------------------------------------------- + + +def _interval_document(): + return { + "schema_version": 1, + "tables": [interval_table_fixture(source_period=2002)], + } + + +def _interval_preparation_node(document, receipt, intervals, bindings=None): + table = intervals["tables"][0] + bindings = interval_bindings(table) if bindings is None else bindings + params = { + "bindings": canonical_text(bindings), + "references": canonical_text(document), + "references_sha256": reference_document_sha256(document), + "intervals": canonical_text(intervals), + } + if receipt is not None: + params["reference_resolution"] = canonical_text(receipt) + return Node( + "prepare", + "calibration.prepare@1", + population="open", + params=params, + outputs=tuple( + Owned("person", band["indicator"], dtype="bool") for band in table["bands"] + ), + artifact_outputs=(ArtifactOutput("preparation", CALIBRATION_PREPARATION_TYPE),), + ) + + +def _with_interval_inputs(tables, persons): + pattern = [0, -400, 99_999, 100_000, 100_001, 1_000_000, 1_000_001, 7] + statuses = ["included", "included", "included", "excluded"] + tables["person"][INCOME_COLUMN] = [pattern[i % 8] for i in range(persons)] + tables["person"][UNIVERSE_COLUMN] = [statuses[i % 4] for i in range(persons)] + + +def _interval_case(tmp_path): + intervals = _interval_document() + document, effective, receipt = _profile_document(intervals=intervals) + assert effective == intervals + facts = write_facts(tmp_path / "facts.jsonl", toy_facts(CALIBRATION_TARGETS)) + payload, _ = compile_target_surface( + facts, + document, + country=COUNTRY, + references_sha256=reference_document_sha256(document), + reference_resolution=receipt, + ) + frame = toy_frame() + persons = len(frame.table("person")) + context = _context( + _interval_preparation_node(document, receipt, intervals), frame=frame + ) + _with_interval_inputs(context.tables, persons) + prepared = CALIBRATION_PREPARE.run(context) + return intervals, document, receipt, payload, frame, prepared + + +def _interval_problem_context(frame, payload, preparation, prepared_columns): + context = _context( + _problem_node(), + frame=frame, + artifacts={ + "surface": _artifact(payload, TARGET_SURFACE_TYPE), + "preparation": _artifact(preparation, CALIBRATION_PREPARATION_TYPE), + }, + ) + _with_interval_inputs(context.tables, len(frame.table("person"))) + for (entity, name), values in prepared_columns.items(): + context.tables[entity][name] = values.to_numpy(copy=True) + return context + + +def test_interval_preparation_carries_digest_inputs_and_payload(tmp_path): + intervals, _, receipt, _, frame, prepared = _interval_case(tmp_path) + evidence = json.loads(prepared.artifacts["preparation"]) + assert evidence["effective_intervals_sha256"] == reference_document_sha256( + intervals + ) + assert evidence["effective_intervals"] == intervals + (row,) = evidence["interval_inputs"] + persons = frame.table("person") + assert row["table"] == "toy_income" and row["entity"] == "person" + assert row["rows"] == len(persons) + assert row["income_values_sha256"] == ( + reference_intervals_module.interval_input_fingerprint( + [ + [0, -400, 99_999, 100_000, 100_001, 1_000_000, 1_000_001, 7][i % 8] + for i in range(len(persons)) + ] + ) + ) + nil = prepared.columns["person", "toy_income_band_nil"] + b0 = prepared.columns["person", "toy_income_band_b0"] + statuses = [ + ["included", "included", "included", "excluded"][i % 4] + for i in range(len(persons)) + ] + incomes = [ + [0, -400, 99_999, 100_000, 100_001, 1_000_000, 1_000_001, 7][i % 8] + for i in range(len(persons)) + ] + assert nil.tolist() == [ + status == "included" and income <= 0 + for status, income in zip(statuses, incomes, strict=True) + ] + assert b0.tolist() == [ + status == "included" and 0 < income <= 100_000 + for status, income in zip(statuses, incomes, strict=True) + ] + + +def test_problem_binds_boundary_diagnostics_without_changing_targets(tmp_path): + _, document, receipt, payload, frame, prepared = _interval_case(tmp_path) + result = TARGETS_PROBLEM.run( + _interval_problem_context( + frame, payload, prepared.artifacts["preparation"], prepared.columns + ) + ) + decoded = decode_problem(result.artifacts["problem"]) + report = decoded.bindings["interval_diagnostics"] + assert decoded.bindings["interval_diagnostics_sha256"] == reference_document_sha256( + report + ) + assert result.receipt["interval_diagnostics"] == report + assert report["effective_intervals_sha256"] == receipt["effective_intervals_sha256"] + (table,) = report["tables"] + assert table["table"] == "toy_income" + assert table["weight_kind"] == "design" + assert table["publisher_reclassification"] == "unavailable" + evidence = json.loads(prepared.artifacts["preparation"]) + assert ( + table["digests"]["record_order_sha256"] + == (evidence["interval_inputs"][0]["entity_ids_sha256"]) + ) + # The same surface prepared without interval outputs has identical targets. + plain = CALIBRATION_PREPARE.run( + _context( + _preparation_node(document, receipt, _interval_document()), frame=frame + ) + ) + context = _context( + _problem_node(), + frame=frame, + artifacts={ + "surface": _artifact(payload, TARGET_SURFACE_TYPE), + "preparation": _artifact( + plain.artifacts["preparation"], CALIBRATION_PREPARATION_TYPE + ), + }, + ) + context.tables["household"]["prepared_marker"] = 1 + baseline = TARGETS_PROBLEM.run(context) + without = decode_problem(baseline.artifacts["problem"]) + assert "interval_diagnostics" not in without.bindings + np.testing.assert_array_equal( + decoded.problem.target_vector, without.problem.target_vector + ) + np.testing.assert_array_equal( + decoded.problem.target_vector, + [spec.value for spec in decode_target_surface(payload).registry.specs], + ) + + +@pytest.mark.parametrize( + "defect", + [ + "income", + "universe", + "payload", + "dropped_inputs", + "dropped_payload", + "missing_income_column", + ], +) +def test_problem_refuses_stale_interval_preparation(tmp_path, defect): + _, _, _, payload, frame, prepared = _interval_case(tmp_path) + evidence = json.loads(prepared.artifacts["preparation"]) + if defect == "payload": + evidence["effective_intervals"]["tables"][0]["bands"][1]["upper_cent"] = 99_000 + elif defect == "dropped_inputs": + evidence.pop("interval_inputs") + elif defect == "dropped_payload": + evidence.pop("effective_intervals") + context = _interval_problem_context( + frame, payload, canonical_json(evidence), prepared.columns + ) + if defect == "income": + context.tables["person"].loc[0, INCOME_COLUMN] = 100_001 + elif defect == "universe": + context.tables["person"].loc[0, UNIVERSE_COLUMN] = "excluded" + elif defect == "missing_income_column": + context.tables["person"].pop(INCOME_COLUMN) + with pytest.raises(ValueError, match="preparation|missing"): + TARGETS_PROBLEM.run(context) + + +def test_missing_diagnostic_entity_refuses_as_missing_evidence(): + table = reference_intervals_module.interval_table( + interval_table_fixture(entity="tax_unit", source_period=2002) + ) + with pytest.raises(ValueError, match="missing evidence"): + target_kernels_module._interval_diagnostics( + toy_frame(), [table], ENTITIES, "0" * 64 + ) + + +@pytest.mark.parametrize( + "defect", ["wrong_document", "no_receipt", "no_document", "unresolved"] +) +def test_preparation_refuses_wrong_unbound_or_unresolved_intervals(tmp_path, defect): + intervals = _interval_document() + document, _, receipt = _profile_document(intervals=intervals) + supplied = deepcopy(intervals) + if defect == "wrong_document": + supplied["tables"][0]["bands"][1]["upper_cent"] = 99_000 + node = _interval_preparation_node( + document, None if defect == "no_receipt" else receipt, supplied + ) + if defect == "no_document": + document, _, receipt = _profile_document() + node = _interval_preparation_node(document, receipt, intervals) + node = replace( + node, params={k: v for k, v in node.params.items() if k != "intervals"} + ) + frame = toy_frame() + context = _context(node, frame=frame) + _with_interval_inputs(context.tables, len(frame.table("person"))) + if defect == "unresolved": + context.tables["person"].loc[1, UNIVERSE_COLUMN] = "unresolved" + with pytest.raises(ValueError): + CALIBRATION_PREPARE.run(context) + + +@pytest.mark.parametrize( + "kernel", [CALIBRATION_PREPARE, TARGETS_PROBLEM], ids=lambda k: k.ref +) +def test_interval_module_source_changes_preparation_and_problem_identity( + tmp_path, monkeypatch, kernel +): + before = kernel.implementation_hash() + source = Path(reference_intervals_module.__file__) + changed = tmp_path / source.name + changed.write_bytes(source.read_bytes() + b"\n# interval helper mutation\n") + monkeypatch.setattr(reference_intervals_module, "__file__", str(changed)) + assert kernel.implementation_hash() != before diff --git a/packages/microcosm-build/tests/golden/nz_country_spec.json b/packages/microcosm-build/tests/golden/nz_country_spec.json index fb0a05908f..dbe3e1216e 100644 --- a/packages/microcosm-build/tests/golden/nz_country_spec.json +++ b/packages/microcosm-build/tests/golden/nz_country_spec.json @@ -1,6 +1,6 @@ { "country": "nz", - "fingerprint": "39da98e8f11e7503245582f0b1f3422f23657ddcc2237d10b99dc59d275fad30", + "fingerprint": "821473b6170ccb7c37e1dcc9934ce531e0963f1ce1f90e4e9a75ec68bcad0b31", "gate_ids": [ "calibration_per_family_fit", "demography_per_family_fit", @@ -46,15 +46,17 @@ "benefit_unit_rule.json": "a9e8cbfd38a64d2f8db0002fe8c31bb5a18fb34dbe59fa943336487ce95e2ca8", "calibration_bindings.json": "2293672e396407a24caaa5788638e7a1e7fc962575bc2551f500fbc309c3fe32", "chronicle_feed.json": "60a80dd0042838b0412baf9dd0985c961b4253a6876d16bcdbb8a2c6c03de0c7", - "country_package.json": "0c367ae03f22c39080693472ecad948df3c1629564130ec13765047346e5d71d", + "country_package.json": "f4a7b068df73d71dc17fe8319b747f7de8e6deee4fcb333dceea77b4c6724f9d", "currency_bridge.json": "aa6a4b286a6a1a015088f32ac013148553422c3d45eeef7d7a15af08388857ca", "export_contract.json": "2c7414fefe395c4f5822643dcd3bb3544ebb2040259aa007b828a99bd01ae210", "gates.json": "fa08b508ce1c93ef7627ca06f3a9e808f8fa6ea6f23ce24fa54c58241bbb9f7f", "geography_spine.json": "5f2b1bdd9f8768249912ffd0fbcb2f7d4ed493b51c74306f793ec12441fd383f", "holdout_references.json": "52b5a2360502156da1392a68350e4e7f61b5fd420fa74428819b65886a9f8655", "precal_references.json": "420361e424405df2312bd21808d6b6f4c3428b6fe90c44c37ab156ce197aa25d", - "reference_inventory.json": "a1356d3c7f91f4025a31a1edc68e2fe78017ec7a5eeb497d91031d4166e3765e", - "reference_profiles.json": "b0f23587f707c4af71eedfc450eae9175886f92e77d732a0e24758df83ec505d", + "reference_aging.json": "4987106611ce14b227e483016b384f6c8103e28311c60384df6adbdfba4ca75d", + "reference_intervals.json": "fcc88c0efd5f416aa15a7d5afbeee1d103dd78a136e13b1efc3973d203188412", + "reference_inventory.json": "d16ac4e95f5427c7bb1382ff6ae90e93d4b48344d810755fcc1dc6514430244a", + "reference_profiles.json": "cbdcb3bc9fe9c64f0f9280b40996545a8b20ec3a3d173fbdc1080c683715e6d5", "release_contract.json": "6cd5e3a4a2bf30e4025e04e964c393b24040937d13db7e6a07b3966a55f3b114", "reporting_classifiers.json": "2700a8dab0bcc186a0ce354a09c7cab127e8b07589b15fb7d63c7f1581041ad8", "scenarios.json": "3f1b5e40d283d7a1baf1a6990f2ca08a0ca39151a8cff028a49455f95e82e9c7", @@ -65,7 +67,7 @@ "spec/sources.yaml": "afdaa4bef98cf520a1c72b6013d1e453162c761cd4b3c1548620184f6ba41297", "spec/spine.yaml": "b3e6a2832ff7671777cae113b7fc45f5e3492bb519526f229118d0851083533e", "spec/vintages.yaml": "1ecc1a3f952bd25b834c394314e8c933ddb5b095fd64ba492dddb03e3cdd803e", - "target_references.json": "39c40fbd2277d68304b141dedd8e01800fd93f58d1950ad7cce8e103e4daeeca" + "target_references.json": "72b2d3b667c782b81b33cc850cd7f8b4014fc4d9fd50e74cb98c29dae1d46a46" }, "resources": [ "spec/bundle.yaml", @@ -88,6 +90,8 @@ "geography_spine.json", "holdout_references.json", "precal_references.json", + "reference_aging.json", + "reference_intervals.json", "reference_inventory.json", "reference_profiles.json", "release_contract.json", diff --git a/test_support/microcosm_build/reference_factor_transport.py b/test_support/microcosm_build/reference_factor_transport.py new file mode 100644 index 0000000000..1fe2f52bb4 --- /dev/null +++ b/test_support/microcosm_build/reference_factor_transport.py @@ -0,0 +1,169 @@ +"""Authenticated toy feed and companion references for transport factor checks.""" + +import json +from copy import deepcopy + +from microcosm.build.ledger_artifact import ( + chronicle_feed_identity, + load_ledger_consumer_artifact, +) +from microcosm.build.reference_factors import resolve_reference_factor +from microcosm.build.reference_profiles import ( + reference_document_sha256, + resolve_reference_profiles, +) +from test_support.microcosm_build.chronicle_feed import write_pinned_artifact +from test_support.microcosm_build.reference_factors import factor_fixture +from test_support.microcosm_build.transport_graph import reference_document + + +def factor_transport_fixture( + tmp_path, *, forged=False, activate=False, manifest_commit=False +): + """Build evidence from loaded lexical tokens; optionally forge its source claim.""" + _, facts, _ = factor_fixture() + references = [] + for kind, value in (("count", 3), ("money", 100)): + key = f"toy-{kind}" + selector = { + "aggregate_fact_key": key, + "source_name": "toy_office", + "source_measure_id": kind, + "source_concept": f"toy.{kind}", + "entity_name": "person", + "period_type": "year", + "period_value": 2001, + "dimensions": ["band"], + "dimension_values": {"band": "one"}, + } + facts.append( + { + "aggregate_fact_key": key, + "label": f"Toy published {kind}", + "value": value, + "assertion": "observation", + "period": {"type": "year", "value": 2001}, + "geography": { + "level": "country", + "id": "XX", + "name": "Toy country", + "vintage": "toy", + }, + "entity": {"name": "person"}, + "dimensions": {"band": "one"}, + "dimension_labels": {"band": "Band"}, + "dimension_value_labels": {"band": {"one": "One"}}, + "aggregation": {"method": "sum"}, + "source": {"source_name": "toy_office"}, + "observed_measure": { + "source_measure_id": kind, + "source_concept": f"toy.{kind}", + "unit": kind, + }, + } + ) + references.append( + { + "name": key, + "entity": "person", + "measure": "people" if kind == "count" else "employment_income", + "family": "toy", + "category_id": "toy.population", + "period": 2002, + "period_match_policy": "latest_not_after", + "ledger_selector": selector, + "metadata": { + "contract_target_id": key, + "reference_value_kind": kind, + "activation_status": "requires_prerequisites", + "required_reference_profile": "index", + "required_measurement_binding": "reviewed_measurement", + "reference_prerequisites": json.dumps( + ["reference_profile:index", "measurement:reviewed_measurement"] + ), + "parking_reason": "Reviewed measurement is required.", + }, + } + ) + path, pin = write_pinned_artifact( + tmp_path / "factor-artifact", json.loads(json.dumps(facts, default=float)) + ) + pin["source_commit"] = "c" * 40 + if manifest_commit: + import hashlib + + manifest_path = path / "manifest.json" + manifest = json.loads(manifest_path.read_text()) + manifest["source_commit"] = pin["source_commit"] + manifest_path.write_text(json.dumps(manifest, sort_keys=True) + "\n") + pin["manifest_sha256"] = hashlib.sha256(manifest_path.read_bytes()).hexdigest() + artifact = load_ledger_consumer_artifact(path, feed_pin=pin, lexical_floats=True) + identity = chronicle_feed_identity(pin) + declaration, _, _ = factor_fixture(feed_identity=identity) + evidence_facts = artifact.facts + if forged: + # This evidence is internally consistent but falsely claims the original pin. + evidence_facts = deepcopy(artifact.facts) + next(row for row in evidence_facts if row["aggregate_fact_key"] == "target-0")[ + "value" + ] = 120 + declaration["expected_operational_factor"]["numerator"] = 1200000 + factor, receipt = resolve_reference_factor(declaration, evidence_facts, identity) + context = { + "schema_version": 1, + "feed_identity": identity, + "factors": [ + { + "declaration": declaration, + "operational_factor": factor, + "receipt": receipt, + } + ], + } + transformation = { + "operation": "scale_money_and_intervals", + "factor_id": declaration["id"], + "reference_names": ["toy-money"], + "count_reference_names": ["toy-count"], + "interval_table_ids": [], + "required_measurement_binding": "reviewed_measurement", + } + profiles = { + "schema_version": 1, + "reference_resource": "target_references", + "factor_context_resource": "factor_context", + "dimensions": { + "index": { + "default": "central", + "profiles": { + name: {"transformations": [deepcopy(transformation)]} + for name in ("low", "central", "high") + }, + } + }, + } + base = reference_document(references) + base["hierarchy"]["target_labels"] = { + row["name"]: f"Aged toy {row['name']}" for row in references + } + document, _, resolution = resolve_reference_profiles( + base, profiles, {}, factor_context=context + ) + if activate: + # Test-only future measurement closure lets the compiler test its own replay + # and arithmetic independently of this lane's parked country declarations. + for row in document["target_references"]: + row["metadata"]["activation_status"] = "active" + resolution["effective_references_sha256"] = reference_document_sha256(document) + resolution.pop("receipt_sha256") + resolution["receipt_sha256"] = reference_document_sha256(resolution) + spec = { + "country": "xx", + "resources": { + "target_references": base, + "reference_profiles": profiles, + "factor_context": context, + "scenarios": {"scenarios": [{"id": "base", "knobs": {}}]}, + }, + } + return path, pin, document, resolution, spec diff --git a/test_support/microcosm_build/reference_factors.py b/test_support/microcosm_build/reference_factors.py new file mode 100644 index 0000000000..ca962f70ab --- /dev/null +++ b/test_support/microcosm_build/reference_factors.py @@ -0,0 +1,185 @@ +"""Small engine-free declarations for exercising public factor interfaces.""" + +from __future__ import annotations + +from copy import deepcopy +from datetime import date, timedelta +from decimal import Decimal + +from microcosm.build.ledger_artifact import CONSUMER_ARTIFACT_SCHEMA_VERSION +from microcosm.build.reference_factors import resolve_reference_factor + + +def factor_fixture( + *, + feed_identity=None, + frequency=2, + source_level="100", + anchor_level="110", + growth="0", + digits=6, + expected_numerator=None, +): + """Return a declaration, exact numeric facts and a matching feed identity. + + Slots are single days: period coverage, rather than calendar conventions, + establishes contiguity. Callers may serialize facts into their toy artifact. + """ + identity = ( + { + "source_commit": "c" * 40, + "facts_sha256": "a" * 64, + "manifest_sha256": "b" * 64, + "artifact_schema_version": CONSUMER_ARTIFACT_SCHEMA_VERSION, + "consumer_fact_schema_versions": ["chronicle.consumer_fact.v4"], + "consumer_fact_schema_sha256": "d" * 64, + "fact_row_count": frequency + 2, + } + if feed_identity is None + else deepcopy(feed_identity) + ) + facts, source, target = [], [], [] + validation = { + "unit": "money_per_week", + "source_sha256": "a" * 64, + "source_vintage": "reviewed", + "entity_role": "employee", + "provenance_class": "survey_aggregate", + "assertion": "observation", + } + for schedule, start, prefix, level in ( + (source, date(2001, 1, 1), "source", source_level), + (target, date(2002, 1, 1), "target", anchor_level), + ): + for index in range(frequency): + period = (start + timedelta(days=index)).isoformat() + coverage = {"start_date": period, "end_date": period} + selector = { + "source_name": "toy_office", + "source_measure_id": "weekly_pay", + "entity_name": "person", + "period_type": "day", + "period_value": period, + "assertion": "observation", + "dimensions": [], + } + slot = { + "selector": selector, + "validation": {**validation, "period_coverage": coverage}, + "weight": "1", + "sequence": index, + } + if schedule is target: + slot["projection_offset"] = index + schedule.append(slot) + if schedule is source or index == 0: + facts.append( + { + "aggregate_fact_key": f"{prefix}-{index}", + "value": Decimal(level), + "assertion": "observation", + "provenance_class": "survey_aggregate", + "period": {"type": "day", "value": period}, + "period_coverage": coverage, + "entity": {"name": "person", "role": "employee"}, + "dimensions": {}, + "source": { + "source_name": "toy_office", + "source_sha256": "a" * 64, + "vintage": "reviewed", + }, + "observed_measure": { + "source_measure_id": "weekly_pay", + "unit": "money_per_week", + }, + } + ) + growth_period = "2002" + growth_validation = { + **validation, + "unit": "percent", + "assertion": "source_projection", + "provenance_class": "model_output", + "period_coverage": {"start_date": "2002-01-01", "end_date": "2002-12-31"}, + "source_column_id": "annual_projection", + } + facts.append( + { + "aggregate_fact_key": "growth", + "value": Decimal(growth), + "assertion": "source_projection", + "provenance_class": "model_output", + "period": {"type": "year", "value": growth_period}, + "period_coverage": growth_validation["period_coverage"], + "entity": {"name": "person", "role": "employee"}, + "dimensions": {}, + "source": { + "source_name": "toy_office", + "source_sha256": "a" * 64, + "vintage": "reviewed", + }, + "observed_measure": {"source_measure_id": "growth", "unit": "percent"}, + "layout": {"source_column_id": "annual_projection"}, + } + ) + if expected_numerator is None: + expected_numerator = int( + Decimal(anchor_level) / Decimal(source_level) * 10**digits + ) + declaration = { + "schema_version": 1, + "id": "toy_factor", + "operation": "projected_period_average_ratio", + "operation_version": 1, + "purpose": "profile_input", + "feed_identity": identity, + "source_period": 2001, + "target_period": 2002, + "source_schedule": source, + "target_schedule": target, + "growth": { + "selector": {"aggregate_fact_key": "growth", "period_value": growth_period}, + "validation": growth_validation, + "unit_multiplier": "0.01", + "scenario_delta": "0", + "sensitivity_provenance": ["toy reviewed sensitivity"], + "assertion_policy": "allow_source_projection", + }, + "subperiods_per_year": frequency, + "projection_policy": "observed_preferred_latest_contiguous", + "rounding": {"digits": digits, "mode": "nearest_half_even"}, + "expected_operational_factor": { + "numerator": expected_numerator, + "denominator": 10**digits, + }, + "validity": { + "declared_on": "2000-01-01", + "valid_from": "2000-01-01", + "valid_until": "2099-12-31", + "as_of": "2002-01-01", + }, + "evidence": ["toy published levels"], + "decision_references": ["toy reviewed decision"], + } + return declaration, facts, identity + + +def factor_context_fixture(**kwargs): + """Return a context with a factor genuinely resolved through the public API.""" + declaration, facts, identity = factor_fixture(**kwargs) + factor, receipt = resolve_reference_factor(declaration, facts, identity) + return ( + { + "schema_version": 1, + "feed_identity": identity, + "factors": [ + { + "declaration": declaration, + "operational_factor": factor, + "receipt": receipt, + } + ], + }, + facts, + identity, + ) diff --git a/test_support/microcosm_build/reference_intervals.py b/test_support/microcosm_build/reference_intervals.py new file mode 100644 index 0000000000..ad7d8bf489 --- /dev/null +++ b/test_support/microcosm_build/reference_intervals.py @@ -0,0 +1,190 @@ +"""Toy interval tables and ageing profiles for exercising interval plumbing.""" + +from __future__ import annotations + +import json +from copy import deepcopy + +from microcosm.build.reference_factors import resolve_reference_factor +from test_support.microcosm_build.reference_factors import factor_fixture +from test_support.microcosm_build.transport_graph import reference_document + +#: Anchor levels against a source level of 100: factors 1.05, 1.1 and 1.15. +PROFILE_ANCHORS = {"low": "105", "central": "110", "high": "115"} +INCOME_COLUMN = "toy_income_cents" +UNIVERSE_COLUMN = "toy_income_universe" + + +def interval_table_fixture( + *, + table_id="toy_income", + entity="person", + cuts=(100_000, 1_000_000), + nil=True, + closure="right", + first=0, + source_period=2001, + target_period=2002, + companions=False, + indicator_prefix="toy_income_band", +): + """One declared table; companions name ``toy_{count,money}_``.""" + bands = [] + if nil: + bands.append( + {"id": "nil", "kind": "nil", "indicator": f"{indicator_prefix}_nil"} + ) + for index, upper in enumerate((*cuts, None)): + bands.append( + { + "id": f"b{index}", + "kind": "positive", + "upper_cent": upper, + "indicator": f"{indicator_prefix}_b{index}", + } + ) + if companions: + for band in bands: + band.update( + count_reference=f"toy_count_{band['id']}", + amount_reference=f"toy_money_{band['id']}", + ) + return { + "id": table_id, + "entity": entity, + "currency": "XTS", + "input_unit": "integer_cent", + "income_column": INCOME_COLUMN, + "universe_column": UNIVERSE_COLUMN, + "source_period": source_period, + "target_period": target_period, + "positive_band_closure": closure, + "nil_band": "present" if nil else "absent", + "negative_income_policy": "floor_zero", + "first_lower_cut_cents": first, + "source_locator": "Toy!A1:A9", + "diagnostics": { + "boundary_window_cents": 100, + "alternative_positive_band_closure": "left" + if closure == "right" + else "right", + }, + "bands": bands, + } + + +def interval_bindings(table, *, entity=None): + """Calibration bindings whose outputs are the table's band indicators.""" + entity = table["entity"] if entity is None else entity + return { + "schema_version": 1, + "required_inputs": {entity: [f"{entity}_id"]}, + "input_domains": {entity: {f"{entity}_id": {"kind": "identity"}}}, + "columns": [ + { + "entity": entity, + "name": band["indicator"], + "interval": {"table": table["id"], "band": band["id"]}, + } + for band in table["bands"] + ], + } + + +def _factor_entry(profile): + declaration, facts, identity = factor_fixture(anchor_level=PROFILE_ANCHORS[profile]) + declaration["id"] = f"toy_{profile}" + factor, receipt = resolve_reference_factor(declaration, facts, identity) + return identity, { + "declaration": declaration, + "operational_factor": factor, + "receipt": receipt, + } + + +def interval_profile_fixture(): + """References, profiles, factor context and intervals for low/central/high. + + Every band has parked count and money companions filtered on its own + indicator; each profile scales the table with its own factor. + """ + table = interval_table_fixture(companions=True) + references = [] + for band in table["bands"]: + for kind in ("count", "money"): + name = f"toy_{kind}_{band['id']}" + references.append( + { + "name": name, + "entity": "person", + "measure": "people" if kind == "count" else "toy_income", + "filter": band["indicator"], + "period": 2002, + "family": "toy", + "category_id": "toy.population", + "period_match_policy": "latest_not_after", + "ledger_selector": { + "aggregate_fact_key": f"toy-{kind}-{band['id']}", + "source_name": "toy_office", + "source_measure_id": kind, + "source_concept": f"toy.{kind}", + "entity_name": "person", + "period_type": "year", + "period_value": 2001, + "dimensions": ["band"], + "dimension_values": {"band": band["id"]}, + }, + "metadata": { + "contract_target_id": name, + "reference_value_kind": kind, + "activation_status": "requires_prerequisites", + "required_reference_profile": "index", + "required_measurement_binding": "reviewed_measurement", + "reference_prerequisites": json.dumps( + [ + "reference_profile:index", + "measurement:reviewed_measurement", + ] + ), + "parking_reason": "Reviewed measurement is required.", + }, + } + ) + identity, factors = None, [] + for profile in PROFILE_ANCHORS: + identity, entry = _factor_entry(profile) + factors.append(entry) + context = {"schema_version": 1, "feed_identity": identity, "factors": factors} + transformation = { + "operation": "scale_money_and_intervals", + "reference_names": [ + row["name"] for row in references if row["name"].startswith("toy_money") + ], + "count_reference_names": [ + row["name"] for row in references if row["name"].startswith("toy_count") + ], + "interval_table_ids": [table["id"]], + "required_measurement_binding": "reviewed_measurement", + } + profiles = { + "schema_version": 1, + "reference_resource": "target_references", + "factor_context_resource": "factor_context", + "interval_resource": "profile_intervals", + "dimensions": { + "index": { + "default": "central", + "profiles": { + profile: { + "transformations": [ + {**deepcopy(transformation), "factor_id": f"toy_{profile}"} + ] + } + for profile in PROFILE_ANCHORS + }, + } + }, + } + base = reference_document(references) + intervals = {"schema_version": 1, "tables": [table]} + return base, profiles, context, intervals diff --git a/tools/generate_nz_reference_aging.py b/tools/generate_nz_reference_aging.py new file mode 100644 index 0000000000..1a4ce04d12 --- /dev/null +++ b/tools/generate_nz_reference_aging.py @@ -0,0 +1,241 @@ +"""Generate NZ's reviewed ageing declarations and authenticated factor receipts. + +Run with ``NZ_CHRONICLE_ARTIFACT`` or ``--artifact``. The six operational +expectations are assertions of the feed calculation, never arithmetic inputs. +The observed-only ratio is diagnostic and is not available to profiles. +""" + +from __future__ import annotations + +import argparse +import copy +import json +import os +from pathlib import Path + +from microcosm.build.ledger_artifact import ( + chronicle_feed_identity, + load_ledger_consumer_artifact, + validate_chronicle_feed_pin, +) +from microcosm.build.reference_factors import resolve_reference_factor +from tools.generate_nz_target_references import SPEC, _selector + +_QES_2025_HASH = "25053dcbd343320cad72e2896475eaebaf5f5bb0b5965ca788506ca15efcea30" +_QES_2026_HASH = "1af2e7e37f1c108a2656842cf1f519c903e1a982bcdc03ee02d0ad888ebc3a97" +_TREASURY_HASH = "e2486375dde515d0722f8c3022f481804bb014beb83c81b8bfc99bc9426544d9" +_OPERANDS = ( + (12028, "2023-Q2", "cfbce1343aa646fce0411631", "1502.27"), + (12030, "2023-Q3", "f9f4f127d080fe2f06617947", "1528.92"), + (12032, "2023-Q4", "fb5938810b7b37ae8534e5f7", "1556.16"), + (12034, "2024-Q1", "854e91ec1dd95e396659ad8e", "1563.54"), + (12044, "2025-Q2", "86ce22ba42a6e2a36b889f9b", "1652.72"), + (12046, "2025-Q3", "434e7b2736b4b16589034c72", "1661.12"), + (12048, "2025-Q4", "bc87e53157eaf53c846879dc", "1681.06"), + (12050, "2026-Q1", "78e735569814069f8066ba9f", "1685.39"), + (12052, "2026-Q2", "91583e3f39d11b8b4b2923d2", "1700.68"), +) +_TY2024 = ("2023-Q2", "2023-Q3", "2023-Q4", "2024-Q1") +_TY2026 = ("2025-Q2", "2025-Q3", "2025-Q4", "2026-Q1") +_TARGET = ("2026-Q2", "2026-Q3", "2026-Q4", "2027-Q1") +_EXPECTED = { + "ird_ty2024_to_ty2027_low": 1115056, + "ird_ty2024_to_ty2027_central": 1117109, + "ird_ty2024_to_ty2027_high": 1119158, + "p1_ty2026_to_ty2027_low": 1026690, + "p1_ty2026_to_ty2027_central": 1028580, + "p1_ty2026_to_ty2027_high": 1030467, + "observed_ty2026_over_ty2024": 1086069, +} +_DECISIONS = [ + "d1599; IRD band ageing factors, 22 October 2026", + "G8-r2 hub rulings 3, 23 October 2026, sections 1–2", +] + + +def _coverage(period): + year, quarter = period.split("-Q") + year, quarter = int(year), int(quarter) + start_month = 3 * quarter - 2 + end_day = (31, 30, 30, 31)[quarter - 1] + return { + "start_date": f"{year:04d}-{start_month:02d}-01", + "end_date": f"{year:04d}-{start_month + 2:02d}-{end_day}", + } + + +def _validation(fact): + return { + "unit": fact["observed_measure"]["unit"], + "source_sha256": fact["source"]["source_sha256"], + "source_vintage": fact["source"]["vintage"], + "entity_role": fact["entity"]["role"], + "provenance_class": fact["provenance_class"], + "assertion": fact["assertion"], + "period_coverage": { + key: fact["period_coverage"][key] for key in ("start_date", "end_date") + }, + "source_column_id": fact["layout"]["source_column_id"], + } + + +def build_aging_declarations(artifact, *, package_dir=SPEC): + """Author the reviewed fixed selectors, refusing a changed operand or pin.""" + feed_pin = json.loads((package_dir / "chronicle_feed.json").read_text()) + validate_chronicle_feed_pin(artifact, feed_pin) + feed_pin = chronicle_feed_identity(feed_pin) + facts_by_key = {fact["aggregate_fact_key"]: fact for fact in artifact.facts} + qes = {} + for _line, period, suffix, expected in _OPERANDS: + fact = facts_by_key[f"ledger.aggregate_fact.v2:{suffix}"] + if str(fact["value"]) != expected or fact["period"]["value"] != period: + raise ValueError(f"Reviewed QES operand changed for {period}") + historical = period in _TY2024 + expected_hash = _QES_2025_HASH if historical else _QES_2026_HASH + if ( + fact["source"]["source_sha256"] != expected_hash + or fact["observed_measure"]["source_measure_id"] != "SBSZ9A" + or fact["observed_measure"]["unit"] != "nzd_per_week" + or fact["assertion"] != "observation" + ): + raise ValueError(f"Reviewed QES evidence changed for {period}") + qes[period] = fact + treasury = facts_by_key["ledger.aggregate_fact.v2:aba7d3d54489b068116e6a25"] + if ( + str(treasury["value"]) != "2.7" + or treasury["period"]["value"] != 2026 + or treasury["source"]["source_sha256"] != _TREASURY_HASH + or treasury["layout"]["source_column_id"] != "year_ending_30_june_2027" + ): + raise ValueError("Reviewed PREFU operand changed") + + def schedule(periods, *, target=False): + result = [] + for index, period in enumerate(periods): + fact = qes.get(period, qes["2026-Q2"]) + selector = _selector(fact, pin_key=period in qes) + selector["assertion"] = "observation" + selector["period_value"] = period + selector["record_set_id"] = ( + f"stats_nz.qes.awe.{period.lower().replace('-', '')}" + ) + validation = _validation(fact) + validation["period_coverage"] = _coverage(period) + slot = { + "selector": selector, + "validation": validation, + "weight": "1", + "sequence": index, + } + if target: + slot["projection_offset"] = index + result.append(slot) + return result + + growth_selector = _selector(treasury) + growth_selector["assertion"] = "source_projection" + growth_selector["source_table"] = treasury["observed_measure"]["source_table"] + declarations = [] + for prefix, periods, source_period in ( + ("ird_ty2024", _TY2024, 2024), + ("p1_ty2026", _TY2026, 2026), + ): + for profile, delta in (("low", "-0.5"), ("central", "0"), ("high", "0.5")): + factor_id = f"{prefix}_to_ty2027_{profile}" + declarations.append( + { + "schema_version": 1, + "id": factor_id, + "operation": "projected_period_average_ratio", + "operation_version": 1, + "purpose": "profile_input", + "feed_identity": copy.deepcopy(feed_pin), + "source_period": source_period, + "target_period": 2027, + "source_schedule": schedule(periods), + "target_schedule": schedule(_TARGET, target=True), + "growth": { + "selector": copy.deepcopy(growth_selector), + "validation": _validation(treasury), + "unit_multiplier": "0.01", + "scenario_delta": delta, + "assertion_policy": "allow_source_projection", + "sensitivity_provenance": [ + "d1599: symmetric ±0.5 percentage-point Microcosm sensitivity; high is not a Treasury forecast path" + ], + }, + "subperiods_per_year": 4, + "projection_policy": "observed_preferred_latest_contiguous", + "rounding": {"digits": 6, "mode": "nearest_half_even"}, + "expected_operational_factor": { + "numerator": _EXPECTED[factor_id], + "denominator": 1000000, + }, + "validity": { + "declared_on": "2026-10-23", + "valid_from": "2026-10-23", + "valid_until": "2026-11-03", + "as_of": "2026-10-23", + }, + "evidence": [ + "Stats NZ QES Table 7; QEMQ.SBSZ9A; ordinary-time FTE, all sectors, actual", + "Treasury PREFU 2026 Table 4.1; year ending 30 June 2027; Chronicle period 2026", + ], + "decision_references": list(_DECISIONS), + } + ) + diagnostic = copy.deepcopy(declarations[1]) + diagnostic.update( + { + "id": "observed_ty2026_over_ty2024", + "purpose": "diagnostic", + "target_period": 2026, + "target_schedule": schedule(_TY2026, target=True), + "growth": None, + "expected_operational_factor": { + "numerator": _EXPECTED["observed_ty2026_over_ty2024"], + "denominator": 1000000, + }, + } + ) + declarations.append(diagnostic) + return feed_pin, declarations + + +def build_reference_aging(artifact, *, package_dir=SPEC): + feed_pin, declarations = build_aging_declarations(artifact, package_dir=package_dir) + records = [] + for declaration in declarations: + factor, receipt = resolve_reference_factor( + declaration, artifact.facts, feed_pin + ) + records.append( + { + "declaration": declaration, + "operational_factor": factor, + "receipt": receipt, + } + ) + return {"schema_version": 1, "feed_identity": feed_pin, "factors": records} + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--artifact", default=os.environ.get("NZ_CHRONICLE_ARTIFACT")) + parser.add_argument("--out", type=Path, default=SPEC / "reference_aging.json") + parser.add_argument("--check", action="store_true") + args = parser.parse_args() + if not args.artifact: + parser.error("--artifact or NZ_CHRONICLE_ARTIFACT is required") + artifact = load_ledger_consumer_artifact(args.artifact, lexical_floats=True) + document = build_reference_aging(artifact) + encoded = json.dumps(document, ensure_ascii=False, indent=2) + "\n" + if args.check: + if args.out.read_text() != encoded: + raise SystemExit(f"Stale generated resource: {args.out}") + else: + args.out.write_text(encoded) + + +if __name__ == "__main__": + main() diff --git a/tools/generate_nz_target_references.py b/tools/generate_nz_target_references.py index 1a3f309a81..38d31b7384 100644 --- a/tools/generate_nz_target_references.py +++ b/tools/generate_nz_target_references.py @@ -12,7 +12,9 @@ import json import math import os +import re from collections import Counter +from decimal import Decimal from pathlib import Path from microcosm.build.ledger_artifact import load_ledger_consumer_artifact @@ -79,7 +81,39 @@ "disclosed national-growth proxy." ) FAMILY_REASON = "Stats NZ Census-family nucleus standard and deterministic roster producer are not encoded; MC7 benefit units and family labels cannot substitute for Census multiplicities." -IRD_REASON = "G8-r2: reviewed IRD-definition taxable-income binding, component closure, record universe, numerical intervals and B5 ageing remain required." +IRD_REASON = "B4: reviewed IRD-definition taxable-income measurement, annual component closure and record universe remain required. Ageing resolution does not establish that measurement." +IRD_MEASUREMENT_BINDING = "ird_taxable_income_ty2027_v1" +# Reviewed national detail-row map: nil row 8 through open tail row 244. +# Published national total row 246 is diagnostic and is deliberately absent. +IRD_NATIONAL_ROWS = tuple(f"row_{row}" for row in range(8, 245)) +IRD_AGE_ROWS = tuple(f"row_{row}" for row in range(6, 189)) +IRD_NATIONAL_TABLE = "ird_taxable_income_national_ty2024" +IRD_AGE_TABLE = "ird_taxable_income_age_ty2024" +# Columns name the d1952 stand-in measure, not IRD's taxable-income definition. +IRD_PROXY_INCOME_COLUMN = "ird_taxable_income_proxy_cents" +IRD_PROXY_UNIVERSE_COLUMN = "ird_taxable_income_proxy_universe_status" +# Rows whose published lower label repeats the previous row's upper endpoint. +IRD_SHARED_ENDPOINT_ROWS = { + IRD_NATIONAL_TABLE: ("row_30", "row_60", "row_90", "row_230"), + IRD_AGE_TABLE: ("row_28", "row_58", "row_88"), +} +INTERVAL_DISCLOSURE = ( + "IRD publishes no band closure or cents semantics for these tables. The " + "cuts, closure, nil band and integer-cent arithmetic are Microcosm's declared " + "convention (G8-r open rulings 2, section 1, 23 October 2026), not IRD's own " + "semantics: t = max(0, x) in integer cents with no dollar rounding; t == 0 is " + "the nil band, including qualifying loss records; each positive band is " + "previous_upper < t <= upper; and the open tail is t > its lower cut. Four " + "published label pairs share an endpoint ($20,000, $50,000, $80,000 and " + "$300,000: national rows 29/30, 59/60, 89/90 and 229/230; age rows 27/28, " + "57/58 and 87/88); the ordered right-closed cuts assign each shared endpoint " + "to the lower band. Ageing scales every finite cut exactly by the selected " + "factor and keeps fractional cents. The income and universe columns name the " + "d1952 stand-in measure rather than IRD's definition; no producer exists yet " + "(G8-r2c) and no active row requests them. Boundary diagnostics report " + "weighted mass within $1 of every cut and the fixed-weight change under the " + "left-closed alternative; publisher reclassification is unavailable." +) RECEIPT_REASON = "G8-w: age-stratified receipt assignment is not supported by the current total-only receipt kernel; preserve the source snapshot and age filters." NZS_REASON = "NZ Super receipt binding and prepared receipt flag are not implemented." VP_REASON = "Veterans Pension is unsupported: no veteran facts or producer; a missing flag must refuse, never default to false." @@ -537,8 +571,10 @@ def build_reference_documents(artifact, *, package_dir=SPEC): (f for f in facts if f["layout"]["table_record_kind"] == "detail"), key=lambda f: int(f["layout"]["source_row_id"].removeprefix("row_")), ) - if len(details) != 237: - raise ValueError("Expected 237 taxable-income detail bands") + if tuple(f["layout"]["source_row_id"] for f in details) != IRD_NATIONAL_ROWS: + raise ValueError( + "Expected the reviewed 237 taxable-income detail rows 8–244" + ) for fact in details: row_id = fact["layout"]["source_row_id"] targets.append( @@ -550,12 +586,26 @@ def build_reference_documents(artifact, *, package_dir=SPEC): measure=column, family="income", period=2027, - status="requires_g8r2_taxable_income_contract_intervals_and_ageing", + status="requires_prerequisites", reason=IRD_REASON, filter_column=f"taxable_income_band_{row_id}_indicator", label=f"TY2026-27 {contract.replace('_', ' ')} {fact['dimensions']['taxable_income_band_source_label']} (parked)", ) ) + targets[-1]["metadata"].update( + { + "reference_prerequisites": json.dumps( + [ + "reference_profile:aging_index", + f"measurement:{IRD_MEASUREMENT_BINDING}", + ], + separators=(",", ":"), + ), + "required_reference_profile": "aging_index", + "required_measurement_binding": IRD_MEASUREMENT_BINDING, + "reference_value_kind": "count" if column == "people" else "money", + } + ) wage_facts = inventory.cells( "ird_wage_salary_distribution.ty2026.income_bands", measure="individuals" ) @@ -705,6 +755,7 @@ def build_reference_documents(artifact, *, package_dir=SPEC): "identity", "rolled_forward_by_ratio", "allocated_residual_by_ratio", + "linear_combination", ] if reference_set == "calibration" else ["identity"], @@ -713,12 +764,182 @@ def build_reference_documents(artifact, *, package_dir=SPEC): } documents["calibration_bindings.json"] = calibration_bindings() documents["reference_profiles.json"] = _reference_profiles(inventory, targets) + documents["reference_intervals.json"] = _reference_intervals(inventory) documents["reference_inventory.json"] = _receipts( inventory, erp, documents, feed_pin, ta_facts ) return documents +def _national_upper_dollars(row): + if row == 9: + return 100 + if row == 10: + return 1000 + if 11 <= row <= 209: + return 1000 * (row - 9) + if 210 <= row <= 229: + return 200000 + 5000 * (row - 209) + if 230 <= row <= 243: + return 300000 + 50000 * (row - 229) + if row == 244: + return None + raise ValueError(f"No national taxable-income cut for row {row}") + + +def _age_upper_dollars(row): + if row == 7: + return 100 + if row == 8: + return 1000 + if 9 <= row <= 187: + return 1000 * (row - 7) + if row == 188: + return None + raise ValueError(f"No age-table taxable-income cut for row {row}") + + +def _label_bounds(label): + """Read a published band label as (lower, upper) dollars; upper None is open.""" + if label == "nil": + return None + match = re.fullmatch(r"\$([\d,]+(?:\.\d+)?)\s*-\s*\$([\d,]+)", label) + if match: + lower, upper = match.groups() + return Decimal(lower.replace(",", "")), Decimal(upper.replace(",", "")) + match = re.fullmatch(r"Over \$([\d,]+)", label) + if match: + return Decimal(match.group(1).replace(",", "")), None + raise ValueError(f"Unreadable taxable-income band label {label!r}") + + +def _band_labels(facts, rows): + labels = {} + for fact in facts: + if fact["layout"]["table_record_kind"] != "detail": + continue + row = fact["layout"]["source_row_id"] + label = fact["dimensions"]["taxable_income_band_source_label"] + if labels.setdefault(row, label) != label: + raise ValueError(f"Taxable-income row {row} has inconsistent labels") + if tuple(sorted(labels, key=lambda row: int(row[4:]))) != rows: + raise ValueError("Taxable-income detail rows differ from the reviewed roster") + return labels + + +def _interval_table(table_id, rows, labels, upper_dollars, locator, companions): + """Generate cuts from the row formulas and check them against the labels.""" + bands, previous, shared = [], Decimal(0), [] + for row_id in rows: + row = int(row_id.removeprefix("row_")) + label = labels[row_id] + bounds = _label_bounds(label) + indicator = ( + f"taxable_income_band_{row_id}_indicator" + if companions + else f"taxable_income_age_table_band_{row_id}_indicator" + ) + band = {"id": row_id} + if bounds is None: + if row_id != rows[0]: + raise ValueError("Only the first taxable-income row is nil") + band.update(kind="nil") + else: + upper = upper_dollars(row) + lower, published_upper = bounds + if published_upper != (None if upper is None else Decimal(upper)): + raise ValueError(f"Row {row_id} label {label!r} disagrees with its cut") + if lower == previous: + shared.append(row_id) + elif lower != previous + (Decimal("0.01") if previous == 0 else 1): + raise ValueError(f"Row {row_id} label {label!r} leaves a gap") + band.update( + kind="positive", upper_cent=None if upper is None else upper * 100 + ) + if upper is not None: + previous = Decimal(upper) + band.update(indicator=indicator, source_label=label) + if companions: + band.update( + count_reference=f"ird_taxable_income_people_by_band__{row_id}", + amount_reference=f"ird_taxable_income_total_by_band__{row_id}", + ) + bands.append(band) + # "Over $X" names its own lower cut, so the open tail is not a shared label. + shared = tuple(row for row in shared if row != rows[-1]) + if shared != IRD_SHARED_ENDPOINT_ROWS[table_id]: + raise ValueError(f"{table_id} shared endpoint rows changed: {shared}") + return { + "id": table_id, + "entity": "person", + "currency": "NZD", + "input_unit": "integer_cent", + "income_column": IRD_PROXY_INCOME_COLUMN, + "universe_column": IRD_PROXY_UNIVERSE_COLUMN, + "source_period": 2024, + "target_period": 2027, + "positive_band_closure": "right", + "nil_band": "present", + "negative_income_policy": "floor_zero", + "first_lower_cut_cents": 0, + "source_locator": locator, + "diagnostics": { + "boundary_window_cents": 100, + "alternative_positive_band_closure": "left", + }, + "bands": bands, + } + + +def _reference_intervals(inventory): + national = _band_labels( + inventory.cells( + "ird_taxable_income_distribution.ty2024.income_bands", + measure="individuals", + ), + IRD_NATIONAL_ROWS, + ) + age = _band_labels( + inventory.cells("ird_taxable_income_distribution.ty2024.age_by_income_band"), + IRD_AGE_ROWS, + ) + tables = [ + _interval_table( + IRD_NATIONAL_TABLE, + IRD_NATIONAL_ROWS, + national, + _national_upper_dollars, + "Income tables 2001-24!BE8:BE244", + companions=True, + ), + _interval_table( + IRD_AGE_TABLE, + IRD_AGE_ROWS, + age, + _age_upper_dollars, + "A6:A188", + companions=False, + ), + ] + tables[0]["description"] = ( + "National TY2024 taxable-income bands, rows 8-244: one nil band, 235 " + "finite bands and the open tail over $1,000,000. Every band names its " + "parked count and amount references." + ) + tables[1]["description"] = ( + "Age-by-income TY2024 taxable-income bands, rows 6-188: one nil band, " + "181 finite bands and the open tail over $180,000. Declared and " + "validated only; no reference companions and no fit rows." + ) + return { + "schema_version": 1, + "country": "nz", + "description": "Generated by tools/generate_nz_target_references.py from the row formulas and checked against the pinned feed's own band labels.", + "disclosure": INTERVAL_DISCLOSURE, + "tables": tables, + } + + def _allocation_operands(inventory, row, recipients): selector = row["ledger_selector"] region = selector["geography_id"] @@ -791,14 +1012,32 @@ def _reference_profiles(inventory, rows): profiles[profile] = {"transformations": transformations} return { "schema_version": 1, + "factor_context_resource": "reference_aging.json", + "interval_resource": "reference_intervals.json", "dimensions": { "census_residual_allocation": {"default": "mar", "profiles": profiles}, "aging_index": { "default": "central", "profiles": { - "central": {"transformations": [], "deferred": True}, - "low": {"available": False, "transformations": []}, - "high": {"available": False, "transformations": []}, + profile: { + "transformations": [ + { + "operation": "scale_money_and_intervals", + "factor_id": f"ird_ty2024_to_ty2027_{profile}", + "reference_names": [ + f"ird_taxable_income_total_by_band__{row_id}" + for row_id in IRD_NATIONAL_ROWS + ], + "count_reference_names": [ + f"ird_taxable_income_people_by_band__{row_id}" + for row_id in IRD_NATIONAL_ROWS + ], + "interval_table_ids": [IRD_NATIONAL_TABLE], + "required_measurement_binding": IRD_MEASUREMENT_BINDING, + } + ] + } + for profile in ("low", "central", "high") }, }, }, @@ -1017,7 +1256,7 @@ def _receipts(inventory, erp, documents, feed_pin, ta_facts): ), ( "qes_prefu_and_b5_ageing", - "G8-r2; QES/PREFU rows are present in the pinned artifact but unused by this residual-allocation task.", + "QES/PREFU feed rows support the declared factor calculations in reference_aging.json; they never become direct calibration references or carried target values.", ), ( "wff_tripwires",