From d28668722a65171643551a9fdd016f8ce4489732 Mon Sep 17 00:00:00 2001 From: John Menke Date: Sun, 1 Nov 2026 14:11:41 -0500 Subject: [PATCH] Fail the address scan when a tracked file cannot be read. An undecodable text file was skipped, so the scan treated that tree as empty. Co-authored-by: Cursor --- src/local_coding_slm/safety.py | 4 ++-- tests/test_safety.py | 28 +++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/local_coding_slm/safety.py b/src/local_coding_slm/safety.py index 192119b..a6af58f 100644 --- a/src/local_coding_slm/safety.py +++ b/src/local_coding_slm/safety.py @@ -387,7 +387,7 @@ def git_tracked_text_files(root: Path) -> list[tuple[str, str]] | None: try: text = path.read_text(encoding="utf-8") except (OSError, UnicodeDecodeError): - continue + return None out.append((str(path.relative_to(root)), text)) return out @@ -400,7 +400,7 @@ def _committed_ip_result( return classify_tracked_ipv4(list(tracked)) files = git_tracked_text_files(repo) if files is None: - return CheckResult("committed_ips", "fail", "could not list tracked files") + return CheckResult("committed_ips", "fail", "could not read tracked files") return classify_tracked_ipv4(files) diff --git a/tests/test_safety.py b/tests/test_safety.py index e9eab30..cf36946 100644 --- a/tests/test_safety.py +++ b/tests/test_safety.py @@ -235,12 +235,38 @@ def test_git_ls_files_failure_fails_closed(self) -> None: results = run_checks(**safe) ips = next(item for item in results if item.name == "committed_ips") self.assertEqual(ips.status, "fail") - self.assertIn("could not list", ips.message) + self.assertIn("could not read", ips.message) with patch("local_coding_slm.safety.subprocess.run", side_effect=OSError("git missing")): raised = run_checks(**safe) missing = next(item for item in raised if item.name == "committed_ips") self.assertEqual(missing.status, "fail") + def test_unreadable_tracked_file_fails_closed(self) -> None: + """A tracked text file that cannot be decoded is not an empty tree.""" + import subprocess + import tempfile + from pathlib import Path + + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + (root / "notes.md").write_bytes(b"see 8.8.8.8 \xff\n") + subprocess.run(["git", "init"], cwd=root, check=True, capture_output=True) + subprocess.run(["git", "add", "-A"], cwd=root, check=True, capture_output=True) + results = run_checks( + environ={ + "OLLAMA_BASE_URL": "http://127.0.0.1:11434", + "OLLAMA_FAST_MODEL": "qwen3.5:9b", + "OLLAMA_STRONG_MODEL": "devstral-small-2", + }, + listen_rows=[("127.0.0.1", 11434)], + env_ignored=True, + env_example_text="OLLAMA_BASE_URL=http://127.0.0.1:11434\n", + root=root, + ) + ips = next(item for item in results if item.name == "committed_ips") + self.assertEqual(ips.status, "fail") + self.assertIn("could not read", ips.message) + def test_unofficial_library_tag_fails_run_checks(self) -> None: results = run_checks( environ={