[BUG] security-guidance: two TestStop tests read review_model.json instead of the session state file
[!NOTE] On behalf of Marvel Tiyjudy, written by Claude Code (Claude Opus 5.5, claude-opus-5-5, reasoning level high).
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
In the security-guidance plugin, two tests in plugins/security-guidance/tests/test_repo_resolution.py fail since 2.0.9 (anthropics/claude-plugins-official@d182ca4, "follow the newest Opus instead of a pinned release"):
TestStop::test_subagent_stop_reviews_without_consuming_session_stateTestStop::test_subagent_stop_findings_do_not_advance_baseline_or_fire_count
The cause is the test helper _read_state (line 236). It opens the first *.json file it finds in SECURITY_WARNINGS_STATE_DIR:
files = [e.path for e in os.scandir(d) if e.name.endswith(".json")]
Since 2.0.9, default_review_model() in hooks/llm.py writes its cache, review_model.json, to the same directory. After a review has run, the directory holds two JSON files. When scandir returns review_model.json first, the test reads the model cache instead of security_warnings_state_<key>.json. NTFS lists entries in name order, so on Windows that happens every time. On other file systems it depends on directory order.
As far as I can tell this is a test-only bug. The production code reads state files by exact name (session_state.get_state_file), and cleanup_old_state_files only touches security_warnings_state_* files.
What Should Happen?
_read_state should read the session state file and ignore other JSON in the state directory. Both tests should pass, as they did on 2.0.8 (6bfd4e0).
Error Messages/Logs
> assert after["touched_paths"] == before["touched_paths"] != []
E KeyError: 'touched_paths'
tests\test_repo_resolution.py:460: KeyError
> assert after.get("baseline_sha") == before.get("baseline_sha")
E AssertionError: assert None == '8a08a57a6eb1a52452195950afdce8ad0f38461b'
E + where <built-in method get of dict object at 0x...> = {'endpoint': 'd2f60d2c7b5509aa', 'model': None, 'at': 1791208946.3105175}.get
tests\test_repo_resolution.py:507: AssertionError
2 failed in 8.27s
The dict in the second failure is the review_model.json cache (endpoint, model, at), not session state.
Steps to Reproduce
git clone https://github.com/anthropics/claude-plugins-official && cd claude-plugins-official && git checkout d182ca4(currentmain)cd plugins/security-guidance- On Windows, run:
````
python -m pytest -q "tests/test_repo_resolution.py::TestStop::test_subagent_stop_reviews_without_consuming_session_state" "tests/test_repo_resolution.py::TestStop::test_subagent_stop_findings_do_not_advance_baseline_or_fire_count"
- Both fail as above. At
6bfd4e0(2.0.8) the same command passes both.
Narrowing the helper to the session state files makes both pass at d182ca4 (verified):
def _read_state(env):
d = env["SECURITY_WARNINGS_STATE_DIR"]
- files = [e.path for e in os.scandir(d) if e.name.endswith(".json")]
+ files = [e.path for e in os.scandir(d)
+ if e.name.startswith("security_warnings_state_") and e.name.endswith(".json")]
assert files, os.listdir(d)
_read_state_or_empty (line 244) has the same .json filter for its emptiness check, so it may want the same narrowing.
Claude Model
Not applicable (test suite, no model call).
Is this a regression?
Yes, this worked in a previous version.
Last Working Version
security-guidance 2.0.8 (anthropics/claude-plugins-official@6bfd4e0)
Claude Code Version
2.1.289 (Claude Code)
Platform
Anthropic API
Operating System
Windows 11 Enterprise (10.0.26200)
Terminal/Shell
Other (Git Bash), Python 3.14.7, pytest 9.1.1
Additional Information
The plugin README asks for the relevant section of ~/.claude/security/log.txt. That doesn't apply here: the failure is in the test suite, not in a live hook run.
Twelve other tests in the suite fail on Windows at both 2.0.8 and 2.0.9 (repo resolution). They are unrelated and not part of this report.