Skip to content

Cite NZ spec sources by symbol, not line number - #1141

Open
MaxGhenis wants to merge 1 commit into
mainfrom
nz-spec-symbol-citations
Open

MaxGhenis wants to merge 1 commit into
mainfrom
nz-spec-symbol-citations

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Invariant

No NZ spec resource cites a line number of a Python source unless the same resource pins that source at a commit. In practice:

  • This repository's sources are cited by symbol, because their line numbers move under unrelated edits.
  • Another repository's source may be cited by line only when the resource also pins it, through a mapping whose path names the .py file and whose commit is 7–40 hex digits.

The check is unpinned_python_line_citations in test_nz_spec_package.py. It scans every string, mapping keys included, in every NZ package resource (the JSON files and spec/*.yaml).

Scope:

  • Pins match by file name.
  • The recognized line locators are x.py:N, x.py:N-M, x.py:N,M, x.py#LN, x.py LN, x.py line N, x.py, lines N-M, x.py (lines N-M), and the reverse forms lines N-M of x.py and line N in x.py.
  • A line locator that names no .py file is out of scope, for example harness_lines or "lines 1695-1790 of the same file at 302e43b…". Those already sit beside a commit.

Why

benefit_unit_rule.json cited concepts.py:880-919 (the relationship pointer block) and concepts.py lines 892-901 (the "always parent 1" sentence). fe698c9 wrote them against the file at that commit.

The same file also cited executor.py lines 636-643 and lines 1550-1573. Those were exact when this branch was cut from 0daf83c, but #888 has since merged and moved the two functions to lines 638 and 1531. scenarios.json cited the conformance harness as ops main run.py:168, which moves whenever ops main does.

Changes

Resource Was Now
benefit_unit_rule.json pointer_concepts.citation concepts.py:880-919 concepts.py, the "# --- Relationships" block: _pointer("partner_person_id") through _pointer("reference_person_id")
benefit_unit_rule.json dependent-child rule concepts.py lines 892-901 concepts.py _pointer("parent_1_person_id")
benefit_unit_rule.json description (…_structural_columns, executor.py lines 636-643), (_validate_population_declaration, executor.py lines 1550-1573) (microcosm.graph.executor._structural_columns), (microcosm.graph.executor._validate_population_declaration)
scenarios.json MC12 annualisation note (ops main run.py:168) (WEEKS_IN_MODEL_YEAR in TheAxiomFoundation/ops nz-lane/emtr_reproduction/run.py at ba6e7d6e)

as_rate_bridge.json's run.py:N citations are unchanged. Its source block pins nz-lane/emtr_reproduction/run.py at ba6e7d6e4f488fdb2762dfb9d91c90f3238b719c, and the new test asserts that they are scanned and covered by that pin, so the exemption is not vacuous.

Each cited claim was re-read for this PR:

  • At ops ba6e7d6e, run.py:168 is WEEKS_IN_MODEL_YEAR = D365 / D7. That commit is still ops main's head.
  • _pointer("parent_1_person_id")'s definition says "When only one parent is co-resident it is always parent 1."
  • _check_pointers emits parent_order for parent_2 without parent_1.
  • _validate_population_declaration raises when a non-structural node owns an entity id or person membership column.

Tests (engine-free, TestSourceCitations)

  • Committed resources: no unpinned Python line citation in any NZ resource. The harness citations are found, and they are pinned at a 40-hex commit.
  • Regression vectors: each of the five citations this PR replaces is refused.
  • Hypothesis, one property per branch:
    • an unpinned line citation in any locator spelling, at any depth, as a value or as a mapping key, is refused;
    • a commit pin at 7–40 hex for that file covers it;
    • a pin of another file, or a pin at a branch name such as main, HEAD or a 6-hex prefix, does not;
    • symbol citations are not line citations.
  • Differential (spec against source):
    • The pointer names in benefit_unit_rule.json equal the _pointer(...) calls in concepts.py's Relationships block, in order.
    • The citation names that block's first and last pointer.
    • The parent-1 concept definition still says "always parent 1".
    • _check_pointers exists.
    • Every dotted microcosm.* symbol named anywhere in the package resolves through import plus getattr. A missing attribute and a missing shard both raise.

Mutation check. Each of these mutants fails one of the new tests, and each was reverted:

  • dropping "always" from the parent-1 definition;
  • renaming _check_pointers;
  • renaming executor._structural_columns;
  • renaming parent_2_person_id in the block.

On origin/main's JSON, the validator flags all five old citations (2× concepts.py, 2× executor.py, 1× run.py). On this branch it flags none.

Robustness to #1134: with #1134's microcosm-frame/src diff applied on top of this branch, TestSourceCitations and the three country goldens pass (18 passed).

Re-pins

packages/microcosm-build/tests/golden/nz_country_spec.json, regenerated from the loaded spec (3 lines):

  • benefit_unit_rule.json: 9e507e78… → 2dcc3a89…
  • scenarios.json: 5dbf2b96… → 1ca42272…
  • fingerprint: df8850d5… → b7a6622b…

Downstream search:

  • The spec-engine package_fingerprint for NZ moves from d7ef7887… to 45566f35…. No file in this repo pins it, by full hash or by 8-character prefix, and neither does Chronicle at 0f2cd96 or a PolicyEngine-wide code search.
  • spec_sha256 and documentation_sha256 are unchanged, because the legacy JSON is in neither surface.
  • No other file pins the old resource hashes. The sources.yaml contract receipts pin only source_stages.json and geography_spine.json, which are untouched.

Verification

Commands:

  • ruff check .: clean.
  • ruff format --check on the test file: clean.
  • pytest test_nz_spec_package.py test_country_spec.py test_spec_engine_country_bundles.py test_spec_engine_loader.py -p no:cacheprovider --basetemp=.hub-scratch/pytest -o tmp_path_retention_policy=failed: 251 passed.

Only the targeted files were run, not the full suite.

Out of scope

The US spec has the same defect. us/ecps_parity_known_gaps.json cites packages/microcosm-build/src/microcosm/build/us_runtime/asec_pool.py lines 61… and lines 397…, which are in-repo and unpinned. That is filed as a separate follow-up, not changed here.

axiom: n/a: spec citation text and an engine-free test; no policy or rule change.

🤖 Generated with Claude Code

benefit_unit_rule.json cited concepts.py:880-919 and concepts.py lines
892-901 for the relationship pointers. #1120 shifted both ranges by one
line on main, and #1134 (open) adds seven more lines above them: at its
head, lines 892-901 are the partner pointer's text rather than the
"always parent 1" sentence, and 880-919 stops before reference_person_id.
The file also cited executor.py by line, and scenarios.json cited the
harness as "ops main run.py:168", which moves with ops main.

Cite the Relationships block, _pointer("parent_1_person_id"), the
executor functions, and WEEKS_IN_MODEL_YEAR at ops ba6e7d6e instead.
Add unpinned_python_line_citations: no NZ spec resource may cite a line
of a Python source unless it pins that source at a commit (as
as_rate_bridge.json pins the harness), with Hypothesis cases per refusal
branch, plus checks that the cited pointers match the concepts source
and that every dotted microcosm symbol the package names resolves.
Re-pin the two resource hashes and the NZ spec fingerprint in the golden.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant