From e6c2db3bf1f6c4b9ed7dd7f25253c558ba4c954c Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Sat, 22 Aug 2026 13:51:34 -0700 Subject: [PATCH 1/2] Reject a case-only registry name mismatch too (PR #914 round 4) Real fix, a natural extension of the padded-name near-miss check (8de62f9): a registry entry named "fixture" when configure.sh resolves "Fixture" (the GitHub-canonical casing) would silently read as "no description declared" rather than flagging the likely typo - GitHub itself treats repo names case-insensitively, so a same-name- different-case entry is a data-entry mistake, not a different repo. Folded into the same near-miss check (normalize with .strip().casefold() on both sides) rather than a second parallel check. New test case. Declined (reasoning posted to PR #914): CodeRabbit's "preserve interpreter probe failures" - the identical finding already declined on PR #918 citing this same file's own gh_ok() precedent for discarding a capability probe's output; and "reject malformed repository entries" (a null entry in repos) - that belongs to spec/validate.py's whole-registry structural check, and an unrelated malformed entry degrading an unrelated repo's lookup to a safe "nothing declared" (not a wrong value) has a materially different, much wider blast radius than the specific near-miss cases already fixed. --- scripts/tests/test_resolve_description.py | 5 +++++ spec/resolve_description.py | 13 ++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/scripts/tests/test_resolve_description.py b/scripts/tests/test_resolve_description.py index 4be26443..43b8e544 100755 --- a/scripts/tests/test_resolve_description.py +++ b/scripts/tests/test_resolve_description.py @@ -58,6 +58,11 @@ def test_a_padded_name_that_would_otherwise_match_raises_rather_than_reading_as_ with self.assertRaises(resolve_description.ResolveError): resolve_description.resolve_description(registry, "Fixture") + def test_a_case_only_name_mismatch_raises_rather_than_reading_as_absent(self) -> None: + registry = {"repos": [{"name": "fixture", "description": "A short tagline."}]} + with self.assertRaises(resolve_description.ResolveError): + resolve_description.resolve_description(registry, "Fixture") + if __name__ == "__main__": unittest.main() diff --git a/spec/resolve_description.py b/spec/resolve_description.py index aaefd38c..a055bc79 100755 --- a/spec/resolve_description.py +++ b/spec/resolve_description.py @@ -31,13 +31,16 @@ def resolve_description(registry: dict, name: str) -> str | None: Raises ResolveError for anything the caller should fail loud on rather than silently read as absent: a registry that is not an object carrying a `repos` array, an entry whose own name - would match NAME but for leading/trailing whitespace (spec/validate.py rejects that shape too, - so it is never the intended way to spell a mismatch), more than one entry named NAME, or a - declared description description_errors() rejects. + would match NAME once whitespace and case differences are normalized away but not otherwise + (spec/validate.py rejects a padded name outright, and a GitHub repo name is compared + case-insensitively by GitHub itself, so a same-name-different-case entry is a data-entry + mistake rather than a different repo), more than one entry named NAME, or a declared + description description_errors() rejects. """ if not isinstance(registry, dict) or not isinstance(registry.get("repos"), list): raise ResolveError("registry is not an object with a 'repos' array") repos = registry["repos"] + normalized_name = name.strip().casefold() near_miss = next( ( r["name"] @@ -45,13 +48,13 @@ def resolve_description(registry: dict, name: str) -> str | None: if isinstance(r, dict) and isinstance(r.get("name"), str) and r["name"] != name - and r["name"].strip() == name + and r["name"].strip().casefold() == normalized_name ), None, ) if near_miss is not None: raise ResolveError( - f"a registry entry's name {near_miss!r} carries leading/trailing whitespace" + f"a registry entry's name {near_miss!r} differs from {name!r} only by whitespace or letter case" ) matches = [r for r in repos if isinstance(r, dict) and r.get("name") == name] if len(matches) > 1: From 8b0113ca391113741c11e7103955b25d44001af2 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Sat, 22 Aug 2026 13:55:51 -0700 Subject: [PATCH 2/2] Fix a repeated 'description description' docstring typo (PR #919 round 2) Reintroduced the exact typo already fixed once in an earlier commit when I rewrote this docstring to add the case-insensitivity note. --- spec/resolve_description.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/resolve_description.py b/spec/resolve_description.py index a055bc79..c9b75615 100755 --- a/spec/resolve_description.py +++ b/spec/resolve_description.py @@ -35,7 +35,7 @@ def resolve_description(registry: dict, name: str) -> str | None: (spec/validate.py rejects a padded name outright, and a GitHub repo name is compared case-insensitively by GitHub itself, so a same-name-different-case entry is a data-entry mistake rather than a different repo), more than one entry named NAME, or a declared - description description_errors() rejects. + description that description_errors() rejects. """ if not isinstance(registry, dict) or not isinstance(registry.get("repos"), list): raise ResolveError("registry is not an object with a 'repos' array")