From afcbf8201b0cc6ab0dd4a809f4f59cb549a75ca7 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 26 Oct 2026 02:47:16 -0700 Subject: [PATCH 1/3] Held-out registry: a too deeply nested event raises LookupError; test the 64-digit zero before Round 8's review of #580 (APPROVE at b111ad9f) left two low findings: - L1: _event let RecursionError through on an event nested too deeply for the JSON parser (200,000 levels), against the module's own rule that an unreadable event raises LookupError. It failed closed, since resolved_base() catches only LookupError. _event now catches RecursionError as _parse_registry already does. test_a_too_deeply_nested_event_raises covers a push and a pull_request whose payloads would otherwise resolve. - L2: only the 40-digit all-zero before was tested, so a fallback limited to 40 digits survived both modules. test_a_zero_push_boundary_needs_a_created_branch now runs on 40 and 64 digits. It also corrects base_commit's docstring (round 8's N3): the zero before falls back only with created set to true. Both new tests fail on their mutants and pass on the fix. Tiers: unit 18,789 + 6 = 18,795, total 25,365. Co-Authored-By: Claude Opus 5.5 --- .../track_b/holdout_registry.py | 11 +++--- tests/README-tiers.md | 4 +- tests/test_track_b_holdout_registry.py | 37 +++++++++++++++++-- tests/tier_counts.json | 2 +- 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/populace_dynamics/track_b/holdout_registry.py b/src/populace_dynamics/track_b/holdout_registry.py index fc3256c3..019863a1 100644 --- a/src/populace_dynamics/track_b/holdout_registry.py +++ b/src/populace_dynamics/track_b/holdout_registry.py @@ -1362,11 +1362,12 @@ def _landed_union( def _event() -> Mapping[str, Any]: """The GitHub event payload at ``GITHUB_EVENT_PATH``. Raises - ``LookupError`` when it cannot be read or is not a JSON object.""" + ``LookupError`` when it cannot be read, is nested too deeply to parse, + or is not a JSON object.""" path = os.environ.get("GITHUB_EVENT_PATH") try: payload = json.loads(Path(path).read_text(encoding="utf-8")) - except (TypeError, ValueError, OSError) as error: + except (TypeError, ValueError, OSError, RecursionError) as error: raise LookupError(f"cannot read the GitHub event: {error}") from None if not isinstance(payload, Mapping): raise LookupError("the GitHub event is not a JSON object") @@ -1389,9 +1390,9 @@ def base_commit(repository: Path) -> str: Raises ``LookupError`` when none of these resolves, and on a push whose event cannot be read, whose ``before`` commit does not - resolve, or whose all-zero ``before`` comes without ``created``: a - push is compared with its own boundary, never with a nearer commit - that would check less history.""" + resolve, or whose all-zero ``before`` comes without ``created`` set + to true: a push is compared with its own boundary, never with a + nearer commit that would check less history.""" head = _commit(repository, "HEAD") if head is None: raise LookupError(f"no HEAD in {repository}") diff --git a/tests/README-tiers.md b/tests/README-tiers.md index 6daa58ab..bfe3bb66 100644 --- a/tests/README-tiers.md +++ b/tests/README-tiers.md @@ -39,9 +39,9 @@ pytest --collect-only -q -m oracle_policyengine | tail -1 | Tier | Tests at HEAD | |---|---:| -| `unit` | 18,789 | +| `unit` | 18,795 | | `artifact` | 4,271 | | `integration_psid` | 1,471 | | `reproduction_legacy` | 520 | | `oracle_policyengine` | 308 | -| **Total** | **25,359** | +| **Total** | **25,365** | diff --git a/tests/test_track_b_holdout_registry.py b/tests/test_track_b_holdout_registry.py index 3543dbf1..96cb384f 100644 --- a/tests/test_track_b_holdout_registry.py +++ b/tests/test_track_b_holdout_registry.py @@ -2718,18 +2718,20 @@ def test_a_push_compares_with_its_before_commit( assert registry.base_registry(repository) == middle +@pytest.mark.parametrize("digits", [40, 64]) @pytest.mark.parametrize("created", [None, False, "true", 1]) def test_a_zero_push_boundary_needs_a_created_branch( - tmp_path, no_ci_env, monkeypatch, created + tmp_path, no_ci_env, monkeypatch, created, digits ): """GitHub sends an all-zero ``before`` when a push creates its branch, and says so with ``created: true``. Without that the boundary is unknown, so the push raises rather than fall back to the merge base, - which would check less history.""" + which would check less history. A SHA-256 repository's zero has 64 + digits.""" repository = init_repository(tmp_path) first = registered(["candidate"]) commit_registry(repository, first, "registry") - payload = {"before": "0" * 40} + payload = {"before": "0" * digits} if created is not None: payload["created"] = created event = tmp_path / "event.json" @@ -2758,6 +2760,35 @@ def test_an_unset_event_path_raises( registry.pull_request_head() +@pytest.mark.parametrize("event_name", ["push", "pull_request"]) +def test_a_too_deeply_nested_event_raises( + tmp_path, no_ci_env, monkeypatch, event_name +): + """An event nested too deeply for the JSON parser cannot be read: a + push and a pull request each raise ``LookupError``, never + ``RecursionError``, though the payload would otherwise resolve.""" + repository = init_repository(tmp_path) + commit_registry(repository, registered(["candidate"]), "registry") + nested = "[" * 200_000 + "]" * 200_000 + with pytest.raises(RecursionError): + json.loads(nested) + if event_name == "push": + outer = {"before": "0" * 40, "created": True} + else: + outer = {"pull_request": {"head": {"sha": "a" * 40}}} + event = tmp_path / "event.json" + event.write_text( + json.dumps(outer)[:-1] + ', "deep": ' + nested + "}", encoding="utf-8" + ) + monkeypatch.setenv("GITHUB_EVENT_NAME", event_name) + monkeypatch.setenv("GITHUB_EVENT_PATH", str(event)) + with pytest.raises(LookupError): + if event_name == "push": + registry.base_commit(repository) + else: + registry.pull_request_head() + + @pytest.mark.parametrize( "payload", [ diff --git a/tests/tier_counts.json b/tests/tier_counts.json index cab2876f..d0756a4a 100644 --- a/tests/tier_counts.json +++ b/tests/tier_counts.json @@ -1,7 +1,7 @@ { "schema_version": 1, "counts": { - "unit": 18789, + "unit": 18795, "artifact": 4271, "integration_psid": 1471, "reproduction_legacy": 520, From e83fb252162126c68c0abb494f6b847ff194cc5f Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Tue, 27 Oct 2026 04:07:50 -0700 Subject: [PATCH 2/3] Held-out registry: rerun the mutation record on the new source Reran all 79 checks on holdout_registry.py at 0b31ff14 (afcbf820), one check at a time in a clean clone, single core at nice 10; 79 killed, none survived, and the source was restored to 0b31ff14 after each. - Check 76 ("an unset event path leaks TypeError") is re-anchored to the handler tuple that now includes RecursionError. - New check "a too deeply nested event leaks RecursionError" drops RecursionError from that handler: 2 tests fail. - New check "a 64-digit zero push boundary falls back without created" limits the created check to 40-digit boundaries: 4 tests fail. - The zero-boundary check's failed ids now carry the 40/64 parameter. - Every other check's failed-test list is unchanged. - restored_source_sha256 moves from 9ca7fc52 to 0b31ff14. Co-Authored-By: Claude Opus 5.5 --- .../track_b_holdout_registry_mutations.json | 42 +++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/docs/design/track_b_holdout_registry_mutations.json b/docs/design/track_b_holdout_registry_mutations.json index 2adda697..d62cc152 100644 --- a/docs/design/track_b_holdout_registry_mutations.json +++ b/docs/design/track_b_holdout_registry_mutations.json @@ -4,7 +4,7 @@ "admitted_scope": "The held-out data registry's rules on invented registries, temporary git repositories and the committed registry; no population, behavioral or forecast claim.", "mutation_method": "One deliberate production-line change per check; both registry test modules run in full and are expected to fail; original bytes restored before the next check. Failed test ids are pytest's own report node ids, written by a reporting plugin, not parsed from summary lines. No mutated implementation is committed.", "restored_source_sha256": { - "src/populace_dynamics/track_b/holdout_registry.py": "9ca7fc52839d637f29596f369578ff255a528114fe8956c767e4fb3d84ddac5d" + "src/populace_dynamics/track_b/holdout_registry.py": "0b31ff1446e26562b29294bd1ef48c8be7f6d6587c1f8e99881bbacf4da240cf" }, "checks": [ { @@ -893,8 +893,8 @@ }, { "mutation": "an unset event path leaks TypeError", - "old": " except (TypeError, ValueError, OSError) as error:\n raise LookupError(f\"cannot read the GitHub event: {error}\") from None", - "new": " except (ValueError, OSError) as error:\n raise LookupError(f\"cannot read the GitHub event: {error}\") from None", + "old": " except (TypeError, ValueError, OSError, RecursionError) as error:\n raise LookupError(f\"cannot read the GitHub event: {error}\") from None", + "new": " except (ValueError, OSError, RecursionError) as error:\n raise LookupError(f\"cannot read the GitHub event: {error}\") from None", "command": "PYTHONPATH=$PWD/src OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE python -m pytest -q -p no:cacheprovider -rf tests/test_track_b_holdout_registry.py tests/test_track_b_holdout_registry_committed.py", "exit_code": 1, "failed_tests": [ @@ -909,10 +909,38 @@ "command": "PYTHONPATH=$PWD/src OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE python -m pytest -q -p no:cacheprovider -rf tests/test_track_b_holdout_registry.py tests/test_track_b_holdout_registry_committed.py", "exit_code": 1, "failed_tests": [ - "tests/test_track_b_holdout_registry.py::test_a_zero_push_boundary_needs_a_created_branch[1]", - "tests/test_track_b_holdout_registry.py::test_a_zero_push_boundary_needs_a_created_branch[False]", - "tests/test_track_b_holdout_registry.py::test_a_zero_push_boundary_needs_a_created_branch[None]", - "tests/test_track_b_holdout_registry.py::test_a_zero_push_boundary_needs_a_created_branch[true]" + "tests/test_track_b_holdout_registry.py::test_a_zero_push_boundary_needs_a_created_branch[1-40]", + "tests/test_track_b_holdout_registry.py::test_a_zero_push_boundary_needs_a_created_branch[1-64]", + "tests/test_track_b_holdout_registry.py::test_a_zero_push_boundary_needs_a_created_branch[False-40]", + "tests/test_track_b_holdout_registry.py::test_a_zero_push_boundary_needs_a_created_branch[False-64]", + "tests/test_track_b_holdout_registry.py::test_a_zero_push_boundary_needs_a_created_branch[None-40]", + "tests/test_track_b_holdout_registry.py::test_a_zero_push_boundary_needs_a_created_branch[None-64]", + "tests/test_track_b_holdout_registry.py::test_a_zero_push_boundary_needs_a_created_branch[true-40]", + "tests/test_track_b_holdout_registry.py::test_a_zero_push_boundary_needs_a_created_branch[true-64]" + ] + }, + { + "mutation": "a too deeply nested event leaks RecursionError", + "old": " except (TypeError, ValueError, OSError, RecursionError) as error:\n raise LookupError(f\"cannot read the GitHub event: {error}\") from None", + "new": " except (TypeError, ValueError, OSError) as error:\n raise LookupError(f\"cannot read the GitHub event: {error}\") from None", + "command": "PYTHONPATH=$PWD/src OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE python -m pytest -q -p no:cacheprovider -rf tests/test_track_b_holdout_registry.py tests/test_track_b_holdout_registry_committed.py", + "exit_code": 1, + "failed_tests": [ + "tests/test_track_b_holdout_registry.py::test_a_too_deeply_nested_event_raises[pull_request]", + "tests/test_track_b_holdout_registry.py::test_a_too_deeply_nested_event_raises[push]" + ] + }, + { + "mutation": "a 64-digit zero push boundary falls back without created", + "old": " if event.get(\"created\") is not True:\n", + "new": " if len(before) == 40 and event.get(\"created\") is not True:\n", + "command": "PYTHONPATH=$PWD/src OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 OMP_WAIT_POLICY=PASSIVE python -m pytest -q -p no:cacheprovider -rf tests/test_track_b_holdout_registry.py tests/test_track_b_holdout_registry_committed.py", + "exit_code": 1, + "failed_tests": [ + "tests/test_track_b_holdout_registry.py::test_a_zero_push_boundary_needs_a_created_branch[1-64]", + "tests/test_track_b_holdout_registry.py::test_a_zero_push_boundary_needs_a_created_branch[False-64]", + "tests/test_track_b_holdout_registry.py::test_a_zero_push_boundary_needs_a_created_branch[None-64]", + "tests/test_track_b_holdout_registry.py::test_a_zero_push_boundary_needs_a_created_branch[true-64]" ] } ] From 46ef33c14134aef67814dac5aee85556342288dd Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Thu, 29 Oct 2026 13:49:36 -0400 Subject: [PATCH 3/3] Tiers: unit 19,041 + 6 = 19,047 after master 53c7f2d2 Master 53c7f2d2 (#584) has unit 19,041. This branch adds six unit tests: the nested-event test for push and pull_request, and four 64-digit cases of the zero-boundary test. The new total is 25,617, and the README table matches. A full-suite collect, which enforces the manifest, and a `-m unit` collect both confirm the counts. Co-Authored-By: Claude Opus 5.5 --- tests/README-tiers.md | 4 ++-- tests/tier_counts.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/README-tiers.md b/tests/README-tiers.md index 313d8899..222873f4 100644 --- a/tests/README-tiers.md +++ b/tests/README-tiers.md @@ -39,9 +39,9 @@ pytest --collect-only -q -m oracle_policyengine | tail -1 | Tier | Tests at HEAD | |---|---:| -| `unit` | 19,041 | +| `unit` | 19,047 | | `artifact` | 4,271 | | `integration_psid` | 1,471 | | `reproduction_legacy` | 520 | | `oracle_policyengine` | 308 | -| **Total** | **25,611** | +| **Total** | **25,617** | diff --git a/tests/tier_counts.json b/tests/tier_counts.json index ca0b5329..a0d827c6 100644 --- a/tests/tier_counts.json +++ b/tests/tier_counts.json @@ -1,7 +1,7 @@ { "schema_version": 1, "counts": { - "unit": 19041, + "unit": 19047, "artifact": 4271, "integration_psid": 1471, "reproduction_legacy": 520,