@@ -723,6 +723,56 @@ def test_pre_commit_config_passes(self, tmp_path):
723723 assert finding .score >= 60.0
724724 assert any ("pre-commit" in e .lower () for e in finding .evidence )
725725
726+ def test_husky_with_hooks_passes (self , tmp_path ):
727+ """Test that .husky directory with hook scripts passes."""
728+ husky_dir = tmp_path / ".husky"
729+ husky_dir .mkdir ()
730+ (husky_dir / "pre-commit" ).write_text ("#!/bin/sh\n npx lint-staged\n " )
731+ (husky_dir / "commit-msg" ).write_text ("#!/bin/sh\n npx commitlint --edit $1\n " )
732+
733+ repo = _make_repo (tmp_path )
734+ assessor = DeterministicEnforcementAssessor ()
735+ finding = assessor .assess (repo )
736+
737+ assert finding .status == "pass"
738+ assert finding .score >= 60.0
739+ assert any (".husky" in e for e in finding .evidence )
740+ assert any ("pre-commit" in e for e in finding .evidence )
741+ assert any ("commit-msg" in e for e in finding .evidence )
742+
743+ def test_husky_empty_dir_does_not_pass (self , tmp_path ):
744+ """Test that .husky directory without hook scripts only gives partial score."""
745+ husky_dir = tmp_path / ".husky"
746+ husky_dir .mkdir ()
747+
748+ repo = _make_repo (tmp_path )
749+ assessor = DeterministicEnforcementAssessor ()
750+ finding = assessor .assess (repo )
751+
752+ assert finding .status == "fail"
753+ assert finding .score == 10.0
754+ assert any ("no hook scripts" in e for e in finding .evidence )
755+
756+ def test_husky_ignores_underscore_files (self , tmp_path ):
757+ """Test that underscore-prefixed files and non-hook files are ignored."""
758+ husky_dir = tmp_path / ".husky"
759+ husky_dir .mkdir ()
760+ (husky_dir / "_" ).mkdir ()
761+ (husky_dir / "_local" ).write_text ("#!/bin/sh\n echo local\n " )
762+ (husky_dir / ".gitignore" ).write_text ("_\n " )
763+ (husky_dir / "README.md" ).write_text ("# Hooks\n " )
764+ (husky_dir / "pre-commit" ).write_text ("#!/bin/sh\n npx lint-staged\n " )
765+
766+ repo = _make_repo (tmp_path )
767+ assessor = DeterministicEnforcementAssessor ()
768+ finding = assessor .assess (repo )
769+
770+ assert finding .score >= 60.0
771+ evidence_str = " " .join (finding .evidence )
772+ assert "_local" not in evidence_str
773+ assert ".gitignore" not in evidence_str
774+ assert "README.md" not in evidence_str
775+
726776 def test_no_config_fails (self , tmp_path ):
727777 """Test fail when no enforcement config exists."""
728778 repo = _make_repo (tmp_path )
0 commit comments