claude-dev-env 1.41.0 → 1.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/CLAUDE.md +8 -0
  2. package/_shared/pr-loop/scripts/_claude_permissions_common.py +232 -8
  3. package/_shared/pr-loop/scripts/code_rules_gate.py +293 -8
  4. package/_shared/pr-loop/scripts/fix_hookspath.py +96 -5
  5. package/_shared/pr-loop/scripts/grant_project_claude_permissions.py +124 -20
  6. package/_shared/pr-loop/scripts/post_audit_thread.py +4 -4
  7. package/_shared/pr-loop/scripts/pr_loop_shared_constants/claude_permissions_constants.py +90 -0
  8. package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/claude_settings_keys_constants.py +2 -0
  9. package/_shared/pr-loop/scripts/preflight.py +13 -31
  10. package/_shared/pr-loop/scripts/reviews_disabled.py +2 -16
  11. package/_shared/pr-loop/scripts/revoke_project_claude_permissions.py +76 -33
  12. package/_shared/pr-loop/scripts/tests/conftest.py +1 -51
  13. package/_shared/pr-loop/scripts/tests/test_agent_config_carveout.py +385 -0
  14. package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +4 -2
  15. package/_shared/pr-loop/scripts/tests/test_claude_permissions_constants.py +37 -2
  16. package/_shared/pr-loop/scripts/tests/test_claude_settings_keys_constants.py +4 -2
  17. package/_shared/pr-loop/scripts/tests/test_code_rules_gate_constants.py +4 -2
  18. package/_shared/pr-loop/scripts/tests/test_fix_hookspath_constants.py +6 -2
  19. package/_shared/pr-loop/scripts/tests/test_grant_project_claude_permissions.py +2 -2
  20. package/_shared/pr-loop/scripts/tests/test_post_audit_thread.py +1 -2
  21. package/_shared/pr-loop/scripts/tests/test_post_audit_thread_constants.py +4 -2
  22. package/_shared/pr-loop/scripts/tests/test_preflight.py +17 -52
  23. package/_shared/pr-loop/scripts/tests/test_preflight_constants.py +6 -2
  24. package/_shared/pr-loop/scripts/tests/test_revoke_project_claude_permissions.py +5 -3
  25. package/agents/pr-description-writer.md +50 -140
  26. package/docs/PR_DESCRIPTION_GUIDE.md +101 -102
  27. package/hooks/_gh_pr_author_swap_utils.py +1 -1
  28. package/hooks/blocking/bot_mention_comment_blocker.py +4 -10
  29. package/hooks/blocking/code_rules_enforcer.py +217 -99
  30. package/hooks/blocking/code_rules_path_utils.py +8 -1
  31. package/hooks/blocking/destructive_command_blocker.py +1 -1
  32. package/hooks/blocking/es_exe_path_rewriter.py +7 -13
  33. package/hooks/blocking/gh_body_arg_blocker.py +6 -1
  34. package/hooks/blocking/gh_pr_author_enforcer.py +5 -5
  35. package/hooks/blocking/gh_pr_author_restore.py +5 -5
  36. package/hooks/blocking/hedging_language_blocker.py +4 -10
  37. package/hooks/blocking/md_path_exemptions.py +205 -0
  38. package/hooks/blocking/md_to_html_blocker.py +48 -20
  39. package/hooks/blocking/pr_converge_bugteam_enforcer.py +5 -11
  40. package/hooks/blocking/pr_description_enforcer.py +626 -41
  41. package/hooks/blocking/question_to_user_enforcer.py +4 -10
  42. package/hooks/blocking/state_description_blocker.py +6 -12
  43. package/hooks/blocking/tdd_enforcer.py +1 -1
  44. package/hooks/blocking/test_bot_mention_comment_blocker.py +1 -1
  45. package/hooks/blocking/test_code_rules_enforcer.py +3 -3
  46. package/hooks/blocking/test_code_rules_enforcer_any_exempt_files.py +1 -1
  47. package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +0 -2
  48. package/hooks/blocking/test_code_rules_enforcer_comment_string_awareness.py +184 -0
  49. package/hooks/blocking/test_code_rules_enforcer_type_checking_scope.py +82 -0
  50. package/hooks/blocking/test_code_rules_enforcer_unused_imports.py +29 -29
  51. package/hooks/blocking/test_gh_body_arg_blocker.py +7 -8
  52. package/hooks/blocking/test_gh_pr_author_enforcer.py +1 -1
  53. package/hooks/blocking/test_gh_pr_author_restore.py +1 -1
  54. package/hooks/blocking/test_hedging_language_blocker.py +2 -2
  55. package/hooks/blocking/test_md_to_html_blocker.py +463 -8
  56. package/hooks/blocking/test_pr_converge_bugteam_enforcer.py +1 -1
  57. package/hooks/blocking/test_pr_description_enforcer.py +1210 -13
  58. package/hooks/blocking/test_question_to_user_enforcer.py +1 -1
  59. package/hooks/blocking/windows_rmtree_blocker.py +5 -11
  60. package/hooks/diagnostic/hook_log_extractor.py +1 -1
  61. package/hooks/diagnostic/hook_log_init.py +1 -1
  62. package/hooks/diagnostic/hook_log_stop_wrapper.py +1 -1
  63. package/hooks/diagnostic/test_hook_log_extractor.py +1 -1
  64. package/hooks/diagnostic/test_hook_log_init.py +2 -2
  65. package/hooks/diagnostic/test_hook_log_stop_wrapper.py +1 -1
  66. package/hooks/git-hooks/gate_utils.py +1 -1
  67. package/hooks/git-hooks/pre_commit.py +1 -1
  68. package/hooks/git-hooks/pre_push.py +1 -1
  69. package/hooks/git-hooks/test_config.py +5 -5
  70. package/hooks/git-hooks/test_pre_push.py +6 -6
  71. package/hooks/{config → hooks_constants}/code_rules_enforcer_constants.py +37 -0
  72. package/hooks/hooks_constants/code_rules_path_utils_constants.py +28 -0
  73. package/hooks/hooks_constants/md_to_html_blocker_constants.py +82 -0
  74. package/hooks/{config → hooks_constants}/pr_converge_bugteam_enforcer_state.py +1 -1
  75. package/hooks/hooks_constants/pr_description_enforcer_constants.py +154 -0
  76. package/hooks/{config → hooks_constants}/pre_tool_use_stdin.py +1 -1
  77. package/hooks/{config → hooks_constants}/project_paths_reader.py +2 -2
  78. package/hooks/{config → hooks_constants}/test_banned_identifiers_constants.py +1 -1
  79. package/hooks/{config → hooks_constants}/test_dynamic_stderr_handler.py +1 -1
  80. package/hooks/{config → hooks_constants}/test_hardcoded_user_path_constants.py +1 -1
  81. package/hooks/{config → hooks_constants}/test_hook_log_extractor_constants.py +2 -2
  82. package/hooks/hooks_constants/test_md_to_html_blocker_constants.py +110 -0
  83. package/hooks/{config → hooks_constants}/test_messages.py +2 -6
  84. package/hooks/{config → hooks_constants}/test_path_rewriter_constants.py +1 -1
  85. package/hooks/hooks_constants/test_pr_description_enforcer_constants.py +292 -0
  86. package/hooks/{config → hooks_constants}/test_pre_tool_use_stdin.py +2 -2
  87. package/hooks/{config → hooks_constants}/test_project_paths_reader.py +3 -3
  88. package/hooks/{config → hooks_constants}/test_session_env_cleanup_constants.py +1 -1
  89. package/hooks/{config → hooks_constants}/test_setup_project_paths_constants.py +2 -2
  90. package/hooks/{config → hooks_constants}/test_unused_module_import_constants.py +1 -1
  91. package/hooks/lifecycle/pr_converge_bugteam_skill_tracker.py +5 -11
  92. package/hooks/lifecycle/test_pr_converge_bugteam_skill_tracker.py +1 -1
  93. package/hooks/session/gh_pr_author_session_cleanup.py +5 -6
  94. package/hooks/session/session_env_cleanup.py +4 -10
  95. package/hooks/session/test_gh_pr_author_session_cleanup.py +1 -1
  96. package/hooks/session/test_untracked_repo_detector.py +2 -2
  97. package/hooks/session/untracked_repo_detector.py +6 -12
  98. package/hooks/test__gh_pr_author_swap_utils.py +1 -1
  99. package/hooks/validators/run_all_validators.py +16 -5
  100. package/hooks/validators/test_output_formatter.py +46 -0
  101. package/hooks/workflow/doc_gist_auto_publish.py +1 -1
  102. package/hooks/workflow/md_to_html_companion.py +8 -15
  103. package/hooks/workflow/test_md_to_html_companion.py +184 -23
  104. package/package.json +1 -1
  105. package/rules/ask-user-question-required.md +1 -1
  106. package/rules/vault-context.md +1 -1
  107. package/scripts/{config → dev_env_scripts_constants}/timing.py +1 -1
  108. package/scripts/setup_project_paths.py +49 -11
  109. package/scripts/sweep_empty_dirs.py +10 -1
  110. package/scripts/test_setup_project_paths.py +2 -2
  111. package/scripts/test_sweep_empty_dirs.py +2 -6
  112. package/skills/_shared/pr-loop/scripts/_path_resolver.py +1 -1
  113. package/skills/_shared/pr-loop/scripts/build_audit_prompt.py +1 -1
  114. package/skills/_shared/pr-loop/scripts/build_fix_prompt.py +1 -1
  115. package/skills/_shared/pr-loop/scripts/init_loop_state.py +1 -1
  116. package/skills/_shared/pr-loop/scripts/teardown_worktrees.py +1 -1
  117. package/skills/_shared/pr-loop/scripts/write_audit_outcomes.py +2 -2
  118. package/skills/_shared/pr-loop/scripts/write_fix_outcomes.py +2 -2
  119. package/skills/bugteam/PROMPTS.md +1 -1
  120. package/skills/bugteam/SKILL.md +1 -1
  121. package/skills/bugteam/reference/github-pr-reviews.md +1 -1
  122. package/skills/bugteam/scripts/{_claude_permissions_common.py → _bugteam_permissions_common.py} +110 -13
  123. package/skills/bugteam/scripts/bugteam_code_rules_gate.py +1 -13
  124. package/skills/bugteam/scripts/bugteam_fix_hookspath.py +1 -16
  125. package/skills/bugteam/scripts/bugteam_preflight.py +1 -13
  126. package/skills/bugteam/scripts/bugteam_scripts_constants/claude_permissions_common_constants.py +69 -0
  127. package/skills/bugteam/scripts/grant_project_claude_permissions.py +117 -12
  128. package/skills/bugteam/scripts/probe_code_rules_enforcer_check.py +1 -1
  129. package/skills/bugteam/scripts/reflow_skill_md.py +1 -1
  130. package/skills/bugteam/scripts/revoke_project_claude_permissions.py +71 -25
  131. package/skills/bugteam/scripts/{test__claude_permissions_common.py → test__bugteam_permissions_common.py} +4 -4
  132. package/skills/bugteam/scripts/test_agent_config_carveout.py +356 -0
  133. package/skills/bugteam/scripts/test_bugteam_fix_hookspath.py +0 -26
  134. package/skills/bugteam/scripts/{test_claude_permissions_common.py → test_bugteam_permissions_common.py} +3 -66
  135. package/skills/bugteam/scripts/test_bugteam_preflight.py +2 -27
  136. package/skills/bugteam/scripts/windows_safe_rmtree.py +1 -1
  137. package/skills/doc-gist/SKILL.md +1 -1
  138. package/skills/doc-gist/scripts/gist_upload.py +1 -1
  139. package/skills/implement/SKILL.md +66 -0
  140. package/skills/implement/scripts/append_note.py +133 -0
  141. package/skills/implement/scripts/implement_scripts_constants/__init__.py +0 -0
  142. package/skills/implement/scripts/implement_scripts_constants/notes_constants.py +12 -0
  143. package/skills/implement/scripts/test_append_note.py +191 -0
  144. package/skills/pr-converge/pr_converge_skill_constants/__init__.py +0 -0
  145. package/skills/pr-converge/{config → pr_converge_skill_constants}/constants.py +6 -1
  146. package/skills/pr-converge/scripts/check_bugbot_ci.py +2 -2
  147. package/skills/pr-converge/scripts/check_convergence.py +175 -29
  148. package/skills/pr-converge/scripts/check_pending_reviews.py +2 -2
  149. package/skills/pr-converge/scripts/fetch_copilot_reviews.py +2 -2
  150. package/skills/pr-converge/scripts/post_fix_reply.py +2 -2
  151. package/skills/pr-converge/scripts/pr_converge_scripts_constants/__init__.py +0 -0
  152. package/skills/pr-converge/scripts/{config → pr_converge_scripts_constants}/pr_converge_constants.py +1 -1
  153. package/skills/pr-converge/scripts/reflow_skill_md.py +90 -16
  154. package/skills/pr-converge/scripts/test_check_bugbot_ci.py +1 -1
  155. package/skills/pr-converge/scripts/test_check_convergence.py +324 -0
  156. package/skills/pr-converge/scripts/test_reflow_skill_md.py +0 -31
  157. package/skills/refine/SKILL.md +257 -0
  158. package/skills/refine/templates/implementation-notes-template.html +56 -0
  159. package/skills/refine/templates/plan-template.md +60 -0
  160. package/skills/session-log/SKILL.md +98 -233
  161. package/_shared/pr-loop/scripts/config/claude_permissions_constants.py +0 -36
  162. package/hooks/config/pr_description_enforcer_constants.py +0 -19
  163. package/hooks/config/test_pr_description_enforcer_constants.py +0 -82
  164. package/skills/bugteam/scripts/config/claude_permissions_common_constants.py +0 -20
  165. package/skills/bugteam/scripts/test_grant_project_claude_permissions.py +0 -55
  166. package/skills/bugteam/scripts/test_revoke_project_claude_permissions.py +0 -55
  167. package/skills/pr-converge/scripts/evict_cached_config_modules.py +0 -20
  168. package/skills/pr-converge/scripts/test_evict_cached_config_modules.py +0 -22
  169. /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/__init__.py +0 -0
  170. /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/code_rules_gate_constants.py +0 -0
  171. /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/fix_hookspath_constants.py +0 -0
  172. /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/post_audit_thread_constants.py +0 -0
  173. /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/preflight_constants.py +0 -0
  174. /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/reviews_disabled_constants.py +0 -0
  175. /package/hooks/git-hooks/{config.py → git_hooks_constants/__init__.py} +0 -0
  176. /package/hooks/{config → hooks_constants}/__init__.py +0 -0
  177. /package/hooks/{config → hooks_constants}/any_type_config.py +0 -0
  178. /package/hooks/{config → hooks_constants}/banned_identifiers_constants.py +0 -0
  179. /package/hooks/{config → hooks_constants}/blocking_check_limits.py +0 -0
  180. /package/hooks/{config → hooks_constants}/bot_mention_comment_blocker_constants.py +0 -0
  181. /package/hooks/{config → hooks_constants}/convergence_branch_constants.py +0 -0
  182. /package/hooks/{config → hooks_constants}/doc_gist_auto_publish_constants.py +0 -0
  183. /package/hooks/{config → hooks_constants}/dynamic_stderr_handler.py +0 -0
  184. /package/hooks/{config → hooks_constants}/gh_pr_author_swap_constants.py +0 -0
  185. /package/hooks/{config → hooks_constants}/hardcoded_user_path_constants.py +0 -0
  186. /package/hooks/{config → hooks_constants}/hook_log_extractor_constants.py +0 -0
  187. /package/hooks/{config → hooks_constants}/html_companion_constants.py +0 -0
  188. /package/hooks/{config → hooks_constants}/inline_tuple_string_magic_constants.py +0 -0
  189. /package/hooks/{config → hooks_constants}/messages.py +0 -0
  190. /package/hooks/{config → hooks_constants}/path_rewriter_constants.py +0 -0
  191. /package/hooks/{config → hooks_constants}/pr_converge_bugteam_enforcer_constants.py +0 -0
  192. /package/hooks/{config → hooks_constants}/session_env_cleanup_constants.py +0 -0
  193. /package/hooks/{config → hooks_constants}/setup_project_paths_constants.py +0 -0
  194. /package/hooks/{config → hooks_constants}/state_description_blocker_constants.py +0 -0
  195. /package/hooks/{config → hooks_constants}/stuttering_check_config.py +0 -0
  196. /package/hooks/{config → hooks_constants}/stuttering_import_binding_constants.py +0 -0
  197. /package/hooks/{config → hooks_constants}/sys_path_insert_constants.py +0 -0
  198. /package/hooks/{config → hooks_constants}/unused_module_import_constants.py +0 -0
  199. /package/hooks/{config → hooks_constants}/windows_rmtree_blocker_constants.py +0 -0
  200. /package/{skills/_shared/pr-loop/scripts/config → hooks/lifecycle}/__init__.py +0 -0
  201. /package/{skills/bugteam/scripts/config → hooks/session}/__init__.py +0 -0
  202. /package/scripts/{config → dev_env_scripts_constants}/__init__.py +0 -0
  203. /package/skills/{doc-gist/scripts/config → _shared/pr-loop/scripts/skills_pr_loop_constants}/__init__.py +0 -0
  204. /package/skills/_shared/pr-loop/scripts/{config → skills_pr_loop_constants}/path_resolver_constants.py +0 -0
  205. /package/skills/{pr-converge/config → bugteam/scripts/bugteam_scripts_constants}/__init__.py +0 -0
  206. /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/bugteam_code_rules_gate_constants.py +0 -0
  207. /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/bugteam_fix_hookspath_constants.py +0 -0
  208. /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/bugteam_preflight_constants.py +0 -0
  209. /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/probe_code_rules_enforcer_check_constants.py +0 -0
  210. /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/reflow_skill_md_constants.py +0 -0
  211. /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/windows_safe_rmtree_constants.py +0 -0
  212. /package/skills/{pr-converge/scripts/config → doc-gist/scripts/doc_gist_scripts_constants}/__init__.py +0 -0
  213. /package/skills/doc-gist/scripts/{config → doc_gist_scripts_constants}/gist_upload_constants.py +0 -0
  214. /package/skills/pr-converge/scripts/{config → pr_converge_scripts_constants}/reflow_skill_md_constants.py +0 -0
@@ -14,7 +14,7 @@ if _HOOKS_DIR not in sys.path:
14
14
  sys.path.insert(0, _HOOKS_DIR)
15
15
  if _HOOKS_ROOT not in sys.path:
16
16
  sys.path.insert(0, _HOOKS_ROOT)
17
- from config.messages import USER_FACING_ASKUSERQUESTION_NOTICE
17
+ from hooks_constants.messages import USER_FACING_ASKUSERQUESTION_NOTICE
18
18
 
19
19
  CLEAN_DECLARATIVE_MESSAGE = "I applied the rename across both files. The tests pass."
20
20
  TRAILING_QUESTION_MESSAGE = (
@@ -17,18 +17,12 @@ import re
17
17
  import sys
18
18
  from pathlib import Path
19
19
 
20
+ _hooks_dir = str(Path(__file__).resolve().parent.parent)
21
+ if _hooks_dir not in sys.path:
22
+ sys.path.insert(0, _hooks_dir)
20
23
 
21
- def _insert_hooks_tree_for_imports() -> None:
22
- hooks_tree = Path(__file__).resolve().parent.parent
23
- hooks_tree_string = str(hooks_tree)
24
- if hooks_tree_string not in sys.path:
25
- sys.path.insert(0, hooks_tree_string)
26
-
27
-
28
- _insert_hooks_tree_for_imports()
29
-
30
- from config.pre_tool_use_stdin import read_hook_input_dictionary_from_stdin
31
- from config.windows_rmtree_blocker_constants import PYTHON_FILE_EXTENSION
24
+ from hooks_constants.pre_tool_use_stdin import read_hook_input_dictionary_from_stdin # noqa: E402
25
+ from hooks_constants.windows_rmtree_blocker_constants import PYTHON_FILE_EXTENSION # noqa: E402
32
26
 
33
27
 
34
28
  def payload_contains_unsafe_rmtree(payload_text: str) -> bool:
@@ -57,7 +57,7 @@ try:
57
57
  except ImportError:
58
58
  psycopg = None
59
59
 
60
- from config.hook_log_extractor_constants import (
60
+ from hooks_constants.hook_log_extractor_constants import (
61
61
  ATTACHMENT_TYPE_HOOK_ADDITIONAL_CONTEXT,
62
62
  ATTACHMENT_TYPE_HOOK_BLOCKING_ERROR,
63
63
  ATTACHMENT_TYPE_HOOK_SUCCESS,
@@ -22,7 +22,7 @@ try:
22
22
  except ImportError:
23
23
  psycopg = None
24
24
 
25
- from config.hook_log_extractor_constants import (
25
+ from hooks_constants.hook_log_extractor_constants import (
26
26
  CONNECT_TIMEOUT_SECONDS,
27
27
  EXIT_CODE_ENVIRONMENT_MISSING,
28
28
  EXIT_CODE_SUCCESS,
@@ -37,7 +37,7 @@ from pathlib import Path
37
37
  if str(Path(__file__).resolve().parent.parent) not in sys.path:
38
38
  sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
39
39
 
40
- from config.hook_log_extractor_constants import (
40
+ from hooks_constants.hook_log_extractor_constants import (
41
41
  BWS_ACCESS_TOKEN_ENV_VAR,
42
42
  BWS_EXECUTABLE_NAME,
43
43
  BWS_RUN_SEPARATOR,
@@ -25,7 +25,7 @@ if str(_HOOKS_ROOT) not in sys.path:
25
25
  sys.path.insert(0, str(_HOOKS_ROOT))
26
26
 
27
27
  from diagnostic import hook_log_extractor
28
- from config.hook_log_extractor_constants import (
28
+ from hooks_constants.hook_log_extractor_constants import (
29
29
  COMMAND_EXCERPT_MAX_CHARACTERS,
30
30
  EXIT_CODE_UNKNOWN_QUERY,
31
31
  HOOK_CATEGORY_UNCATEGORIZED,
@@ -17,8 +17,8 @@ if str(_HOOKS_ROOT) not in sys.path:
17
17
  sys.path.insert(0, str(_HOOKS_ROOT))
18
18
 
19
19
  from diagnostic import hook_log_init
20
- from config import hook_log_extractor_constants
21
- from config.hook_log_extractor_constants import (
20
+ from hooks_constants import hook_log_extractor_constants
21
+ from hooks_constants.hook_log_extractor_constants import (
22
22
  EXIT_CODE_ENVIRONMENT_MISSING,
23
23
  NEON_DATABASE_URL_ENVIRONMENT_VARIABLE,
24
24
  OUTCOME_INIT_PROBE,
@@ -15,7 +15,7 @@ if str(_HOOKS_ROOT) not in sys.path:
15
15
  sys.path.insert(0, str(_HOOKS_ROOT))
16
16
 
17
17
  from diagnostic import hook_log_stop_wrapper
18
- from config.hook_log_extractor_constants import (
18
+ from hooks_constants.hook_log_extractor_constants import (
19
19
  BWS_ACCESS_TOKEN_ENV_VAR,
20
20
  BWS_EXECUTABLE_NAME,
21
21
  FLAG_INCREMENTAL,
@@ -6,7 +6,7 @@ import os
6
6
  import stat
7
7
  from pathlib import Path
8
8
 
9
- from config import (
9
+ from git_hooks_constants import (
10
10
  CLAUDE_HOME_DEFAULT_SUBDIRECTORY,
11
11
  CLAUDE_HOME_ENV_VAR,
12
12
  GATE_PATH_OVERRIDE_ENV_VAR,
@@ -17,7 +17,7 @@ import subprocess
17
17
  import sys
18
18
  from pathlib import Path
19
19
 
20
- from config import (
20
+ from git_hooks_constants import (
21
21
  GATE_INFRASTRUCTURE_FAILURE_EXIT_CODE,
22
22
  GATE_SCRIPT_NOT_FOUND_MESSAGE,
23
23
  INVOKE_GATE_FAILURE_MESSAGE,
@@ -24,7 +24,7 @@ import subprocess
24
24
  import sys
25
25
  from pathlib import Path
26
26
 
27
- from config import (
27
+ from git_hooks_constants import (
28
28
  ALL_ZEROS_OBJECT_NAME_CHARACTER,
29
29
  BASE_REFERENCE_ARGUMENT,
30
30
  DEFAULT_REMOTE_BASE_REFERENCE,
@@ -15,17 +15,17 @@ for each_module_name in list(sys.modules):
15
15
  del sys.modules[each_module_name]
16
16
  importlib.invalidate_caches()
17
17
 
18
- import config
18
+ import git_hooks_constants
19
19
 
20
20
 
21
21
  def test_pre_push_gate_script_not_found_message_contains_path_placeholder() -> None:
22
- assert "{path}" in config.PRE_PUSH_GATE_SCRIPT_NOT_FOUND_MESSAGE
22
+ assert "{path}" in git_hooks_constants.PRE_PUSH_GATE_SCRIPT_NOT_FOUND_MESSAGE
23
23
 
24
24
 
25
25
  def test_no_parseable_stdin_lines_message_exists_and_describes_problem() -> None:
26
- assert "no parseable stdin lines" in config.NO_PARSEABLE_STDIN_LINES_MESSAGE
26
+ assert "no parseable stdin lines" in git_hooks_constants.NO_PARSEABLE_STDIN_LINES_MESSAGE
27
27
 
28
28
 
29
29
  def test_no_parseable_stdin_lines_sentinel_is_distinct_sentinel_value() -> None:
30
- assert config.NO_PARSEABLE_STDIN_LINES_SENTINEL is not None
31
- assert config.NO_PARSEABLE_STDIN_LINES_SENTINEL != config.DEFAULT_REMOTE_BASE_REFERENCE
30
+ assert git_hooks_constants.NO_PARSEABLE_STDIN_LINES_SENTINEL is not None
31
+ assert git_hooks_constants.NO_PARSEABLE_STDIN_LINES_SENTINEL != git_hooks_constants.DEFAULT_REMOTE_BASE_REFERENCE
@@ -19,7 +19,7 @@ for each_module_name in list(sys.modules):
19
19
  importlib.invalidate_caches()
20
20
 
21
21
  import pre_push
22
- import config
22
+ import git_hooks_constants
23
23
 
24
24
 
25
25
  ALL_ZEROS_OBJECT_NAME: str = "0" * 40
@@ -163,7 +163,7 @@ def test_main_exits_two_when_stdin_raises_ioerror(
163
163
 
164
164
  exit_code = pre_push.main()
165
165
 
166
- assert exit_code == config.GATE_INFRASTRUCTURE_FAILURE_EXIT_CODE
166
+ assert exit_code == git_hooks_constants.GATE_INFRASTRUCTURE_FAILURE_EXIT_CODE
167
167
 
168
168
 
169
169
  def test_main_exits_two_when_invoke_gate_raises_oserror(
@@ -182,7 +182,7 @@ def test_main_exits_two_when_invoke_gate_raises_oserror(
182
182
 
183
183
  exit_code = pre_push.main()
184
184
 
185
- assert exit_code == config.GATE_INFRASTRUCTURE_FAILURE_EXIT_CODE
185
+ assert exit_code == git_hooks_constants.GATE_INFRASTRUCTURE_FAILURE_EXIT_CODE
186
186
 
187
187
 
188
188
  def test_resolve_base_reference_emits_warning_for_malformed_line(
@@ -226,7 +226,7 @@ def test_resolve_base_reference_returns_sentinel_when_only_malformed_lines_prese
226
226
 
227
227
  base_reference = pre_push.resolve_base_reference_from_stdin(malformed_only_stdin)
228
228
 
229
- assert base_reference == config.NO_PARSEABLE_STDIN_LINES_SENTINEL
229
+ assert base_reference == git_hooks_constants.NO_PARSEABLE_STDIN_LINES_SENTINEL
230
230
 
231
231
 
232
232
  def test_main_prints_stderr_when_gate_script_missing(
@@ -253,7 +253,7 @@ def test_resolve_base_reference_exits_two_when_only_malformed_lines_and_no_valid
253
253
 
254
254
  result = pre_push.resolve_base_reference_from_stdin(malformed_only_stdin)
255
255
 
256
- assert result == config.NO_PARSEABLE_STDIN_LINES_SENTINEL
256
+ assert result == git_hooks_constants.NO_PARSEABLE_STDIN_LINES_SENTINEL
257
257
 
258
258
 
259
259
  def test_main_exits_two_when_all_stdin_lines_are_malformed(
@@ -268,7 +268,7 @@ def test_main_exits_two_when_all_stdin_lines_are_malformed(
268
268
 
269
269
  exit_code = pre_push.main()
270
270
 
271
- assert exit_code == config.GATE_INFRASTRUCTURE_FAILURE_EXIT_CODE
271
+ assert exit_code == git_hooks_constants.GATE_INFRASTRUCTURE_FAILURE_EXIT_CODE
272
272
  captured = capsys.readouterr()
273
273
  assert "no parseable stdin lines" in captured.err
274
274
 
@@ -4,6 +4,13 @@ Extracted from code_rules_enforcer.py to satisfy the constants-location rule.
4
4
  """
5
5
 
6
6
  import re
7
+ import tokenize
8
+
9
+ ALL_PYTHON_TOKENIZE_FAILURE_EXCEPTIONS: tuple[type[BaseException], ...] = (
10
+ tokenize.TokenError,
11
+ IndentationError,
12
+ SyntaxError,
13
+ )
7
14
 
8
15
  ALL_PYTHON_EXTENSIONS = {".py"}
9
16
  ALL_JAVASCRIPT_EXTENSIONS = {".js", ".ts", ".tsx", ".jsx"}
@@ -23,7 +30,37 @@ UPPER_SNAKE_CONSTANT_PATTERN = re.compile(r"^[A-Z][A-Z0-9_]*$")
23
30
 
24
31
  TYPE_CHECKING_BLOCK_PATTERN = re.compile(r"^(?P<indent>\s*)if\s+(typing\.)?TYPE_CHECKING\s*:\s*$")
25
32
  ALL_IMPORT_STATEMENT_PREFIXES: tuple[str, ...] = ("import ", "from ")
33
+ ALL_EXEMPT_PYTHON_COMMENT_BODIES: tuple[str, ...] = (
34
+ "type:",
35
+ "noqa",
36
+ "pylint:",
37
+ "pragma:",
38
+ "TODO",
39
+ "FIXME",
40
+ "HACK",
41
+ "XXX",
42
+ )
43
+ ALL_JAVASCRIPT_EXEMPT_COMMENT_PREFIXES: tuple[str, ...] = (
44
+ "// @ts-",
45
+ "// eslint-",
46
+ "// prettier-",
47
+ "/// ",
48
+ "// TODO",
49
+ "// FIXME",
50
+ "// HACK",
51
+ "// XXX",
52
+ )
53
+ ALL_JAVASCRIPT_EXEMPT_INLINE_COMMENT_PREFIXES: tuple[str, ...] = (
54
+ "TODO",
55
+ "FIXME",
56
+ "HACK",
57
+ "XXX",
58
+ )
59
+ MAX_COMMENT_ISSUES = 3
26
60
  NOT_INSIDE_TYPE_CHECKING_BLOCK = -1
61
+ TRIPLE_QUOTE_PARITY_DIVISOR = 2
62
+ TRIPLE_DOUBLE_QUOTE_DELIMITER = '"""'
63
+ TRIPLE_SINGLE_QUOTE_DELIMITER = "'''"
27
64
  FILE_GLOBAL_UPPER_SNAKE_PATTERN = re.compile(r"^_?[A-Z][A-Z0-9_]*$")
28
65
 
29
66
  ALL_COLLECTION_TYPE_NAMES: frozenset[str] = frozenset({
@@ -0,0 +1,28 @@
1
+ """Directory-name allowlist consumed by ``code_rules_path_utils.is_config_file``.
2
+
3
+ ``code_rules_enforcer.py`` and ``validators/exempt_paths.py`` use the
4
+ classifier to decide whether a file is a config file. The classifier
5
+ walks every parent directory segment and returns True when any segment
6
+ matches a name in this set. Keeping the set in ``hooks_constants`` makes
7
+ the classifier importable without a self-exempting hook in the consumer
8
+ module.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+
14
+ ALL_CONFIG_DIRECTORY_NAMES = frozenset(
15
+ {
16
+ "config",
17
+ "hooks_constants",
18
+ "git_hooks_constants",
19
+ "pr_loop_shared_constants",
20
+ "skills_pr_loop_constants",
21
+ "pr_converge_skill_constants",
22
+ "pr_converge_scripts_constants",
23
+ "bugteam_scripts_constants",
24
+ "doc_gist_scripts_constants",
25
+ "implement_scripts_constants",
26
+ "dev_env_scripts_constants",
27
+ }
28
+ )
@@ -0,0 +1,82 @@
1
+ """Configuration constants for the md_to_html_blocker PreToolUse hook
2
+ and its shared exemption helpers (`md_path_exemptions`)."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import os
7
+ import tempfile
8
+
9
+
10
+ ALL_CLAUDE_CODE_SOURCE_TOP_DIRECTORIES: frozenset[str] = frozenset(
11
+ {"agents", "docs", "skills", "rules", "system-prompts", "commands"}
12
+ )
13
+
14
+ PACKAGES_TOP_LEVEL_SEGMENT: str = "packages"
15
+ CLAUDE_DEV_ENV_REPO_NAME_SEGMENT: str = "claude-dev-env"
16
+
17
+ MINIMUM_SEGMENT_COUNT_TO_MATCH_INDICATOR: int = 4
18
+
19
+ ALL_EXEMPT_ANYWHERE_FILENAMES: tuple[str, ...] = ("SKILL.md",)
20
+ ALL_EXEMPT_PLUGIN_DIRECTORY_SEGMENTS: tuple[str, ...] = ("agents", "skills", "commands")
21
+ ALL_EXEMPT_HOME_RELATIVE_DIRECTORIES: tuple[str, ...] = ("SessionLog",)
22
+ ALL_EXEMPT_ROOT_FILENAMES: tuple[str, ...] = ("readme.md", "changelog.md")
23
+ REPO_ROOT_MARKER_NAME: str = ".git"
24
+ CLAUDE_DIRECTORY_NAME: str = ".claude"
25
+ PLUGIN_ROOT_MARKER_DIRECTORY_NAME: str = ".claude-plugin"
26
+
27
+ CLAUDE_DIRECTORY_SEGMENT_MARKER: str = f"/{CLAUDE_DIRECTORY_NAME}/"
28
+ CLAUDE_DIRECTORY_PATH_PREFIX: str = f"{CLAUDE_DIRECTORY_NAME}/"
29
+ PLUGIN_DIRECTORY_SEGMENT_MARKER: str = f"/{PLUGIN_ROOT_MARKER_DIRECTORY_NAME}/"
30
+ PLUGIN_DIRECTORY_PATH_PREFIX: str = f"{PLUGIN_ROOT_MARKER_DIRECTORY_NAME}/"
31
+
32
+ ALL_EXEMPT_ANYWHERE_FILENAMES_LOWER: frozenset[str] = frozenset(
33
+ each_filename.lower() for each_filename in ALL_EXEMPT_ANYWHERE_FILENAMES
34
+ )
35
+ ALL_EXEMPT_ROOT_FILENAMES_LOWER: frozenset[str] = frozenset(
36
+ each_filename.lower() for each_filename in ALL_EXEMPT_ROOT_FILENAMES
37
+ )
38
+
39
+
40
+ def _resolve_canonical_directory_lowercase(directory_path: str) -> str:
41
+ return (
42
+ os.path.realpath(directory_path).replace("\\", "/").rstrip("/").lower()
43
+ )
44
+
45
+
46
+ RESOLVED_HOME_DIRECTORY_LOWER: str = _resolve_canonical_directory_lowercase(
47
+ os.path.expanduser("~")
48
+ )
49
+ RESOLVED_TEMP_DIRECTORY_LOWER: str = _resolve_canonical_directory_lowercase(
50
+ tempfile.gettempdir()
51
+ )
52
+
53
+ ALL_EXEMPT_HOME_DIRECTORY_PATH_PREFIXES: tuple[str, ...] = tuple(
54
+ f"{RESOLVED_HOME_DIRECTORY_LOWER}/{each_relative_directory.lower()}/"
55
+ for each_relative_directory in ALL_EXEMPT_HOME_RELATIVE_DIRECTORIES
56
+ )
57
+ RESOLVED_TEMP_DIRECTORY_PATH_PREFIX: str = f"{RESOLVED_TEMP_DIRECTORY_LOWER}/"
58
+
59
+
60
+ __all__ = [
61
+ "ALL_CLAUDE_CODE_SOURCE_TOP_DIRECTORIES",
62
+ "ALL_EXEMPT_ANYWHERE_FILENAMES",
63
+ "ALL_EXEMPT_ANYWHERE_FILENAMES_LOWER",
64
+ "ALL_EXEMPT_HOME_DIRECTORY_PATH_PREFIXES",
65
+ "ALL_EXEMPT_HOME_RELATIVE_DIRECTORIES",
66
+ "ALL_EXEMPT_PLUGIN_DIRECTORY_SEGMENTS",
67
+ "ALL_EXEMPT_ROOT_FILENAMES",
68
+ "ALL_EXEMPT_ROOT_FILENAMES_LOWER",
69
+ "CLAUDE_DEV_ENV_REPO_NAME_SEGMENT",
70
+ "CLAUDE_DIRECTORY_NAME",
71
+ "CLAUDE_DIRECTORY_PATH_PREFIX",
72
+ "CLAUDE_DIRECTORY_SEGMENT_MARKER",
73
+ "MINIMUM_SEGMENT_COUNT_TO_MATCH_INDICATOR",
74
+ "PACKAGES_TOP_LEVEL_SEGMENT",
75
+ "PLUGIN_DIRECTORY_PATH_PREFIX",
76
+ "PLUGIN_DIRECTORY_SEGMENT_MARKER",
77
+ "PLUGIN_ROOT_MARKER_DIRECTORY_NAME",
78
+ "REPO_ROOT_MARKER_NAME",
79
+ "RESOLVED_HOME_DIRECTORY_LOWER",
80
+ "RESOLVED_TEMP_DIRECTORY_LOWER",
81
+ "RESOLVED_TEMP_DIRECTORY_PATH_PREFIX",
82
+ ]
@@ -14,7 +14,7 @@ import json
14
14
  import os
15
15
  from pathlib import Path
16
16
 
17
- from config.pr_converge_bugteam_enforcer_constants import (
17
+ from hooks_constants.pr_converge_bugteam_enforcer_constants import (
18
18
  CLAUDE_JOB_DIR_ENV_VAR,
19
19
  PR_CONVERGE_STATE_FILENAME,
20
20
  )
@@ -0,0 +1,154 @@
1
+ """Configuration constants for the pr_description_enforcer PreToolUse hook."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import re
7
+ from dataclasses import dataclass
8
+ from pathlib import Path
9
+
10
+
11
+ _PLUGIN_ROOT: str = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
12
+ PR_GUIDE_PATH: str = os.path.join(_PLUGIN_ROOT, "docs", "PR_DESCRIPTION_GUIDE.md")
13
+
14
+ MINIMUM_SUBSTANTIVE_PROSE_CHARS: int = 40
15
+
16
+ FENCED_CODE_BLOCK_PATTERN: re.Pattern[str] = re.compile(r"```.*?```", re.DOTALL)
17
+ INLINE_CODE_PATTERN: re.Pattern[str] = re.compile(r"`[^`]*`")
18
+ HEADING_LINE_PATTERN: re.Pattern[str] = re.compile(r"^#+[ \t].*$", re.MULTILINE)
19
+ BOLD_PAIR_PATTERN: re.Pattern[str] = re.compile(r"\*\*([^*]+?)\*\*")
20
+ BULLET_MARKER_PATTERN: re.Pattern[str] = re.compile(r"^\s*[-*+]\s+", re.MULTILINE)
21
+ BLOCKQUOTE_MARKER_PATTERN: re.Pattern[str] = re.compile(r"^\s*>\s+", re.MULTILINE)
22
+ LINK_TEXT_PATTERN: re.Pattern[str] = re.compile(r"\[([^\]]+)\]\([^)]+\)")
23
+ WHITESPACE_RUN_PATTERN: re.Pattern[str] = re.compile(r"\s+")
24
+
25
+ SUMMARY_HEADER: str = "## Summary"
26
+ PROBLEM_HEADER: str = "## Problem"
27
+ TEST_PLAN_HEADER: str = "## Test plan"
28
+ TESTS_HEADER: str = "## Tests"
29
+ TESTING_HEADER: str = "## Testing"
30
+ VERIFICATION_HEADER: str = "## Verification"
31
+ VALIDATION_HEADER: str = "## Validation"
32
+
33
+ ALL_HEAVY_OPENING_HEADERS: frozenset[str] = frozenset({PROBLEM_HEADER, SUMMARY_HEADER})
34
+ ALL_HEAVY_TESTING_HEADERS: frozenset[str] = frozenset(
35
+ {TEST_PLAN_HEADER, TESTING_HEADER, TESTS_HEADER, VERIFICATION_HEADER, VALIDATION_HEADER}
36
+ )
37
+ GH_PR_COMMAND_MIN_TOKEN_COUNT: int = 3
38
+ ATOMIC_WRITE_TEMP_SUFFIX: str = ".tmp"
39
+ SELF_CLOSING_REFERENCE_MESSAGE_PREFIX: str = "PR body references its own PR number #"
40
+ SELF_CLOSING_REFERENCE_MESSAGE_SUFFIX: str = (
41
+ " as a self-closing keyword (Fixes/Closes/Resolves) -- remove the self-reference"
42
+ )
43
+
44
+ SELF_REFERENCE_PATTERN_TEMPLATE: str = (
45
+ r"\b(?:Close|Closes|Closed|Fix|Fixes|Fixed|Resolve|Resolves|Resolved)"
46
+ r"\s+#{pr_number}\b"
47
+ )
48
+
49
+ THIS_PR_OPENING_PATTERN: re.Pattern[str] = re.compile(
50
+ r"^\s*(?:#[^\n]*\n\s*)*This PR\b",
51
+ re.IGNORECASE,
52
+ )
53
+
54
+ TRIVIAL_SHAPE: str = "trivial"
55
+ STANDARD_SHAPE: str = "standard"
56
+ HEAVY_SHAPE: str = "heavy"
57
+
58
+ TRIVIAL_BODY_CHAR_THRESHOLD: int = 200
59
+ HEAVY_MIN_BODY_CHARS_FOR_CLASSIFICATION: int = 500
60
+
61
+ READABILITY_MAX_SENTENCE_WORDS: int = 28
62
+ READABILITY_AVG_SENTENCE_WORDS: int = 18
63
+ READABILITY_MIN_FLESCH: int = 50
64
+ READABILITY_STRIKE_THRESHOLD: int = 3
65
+
66
+ READABILITY_LOOSEN_CAP: int = 3
67
+ READABILITY_MIN_FLESCH_FLOOR: int = 30
68
+ READABILITY_MAX_SENTENCE_WORDS_CEILING: int = 60
69
+ READABILITY_AVG_SENTENCE_WORDS_CEILING: int = 40
70
+
71
+ READABILITY_FLESCH_LOOSEN_FACTOR: float = 0.9
72
+ READABILITY_SENTENCE_WORDS_LOOSEN_FACTOR: float = 10 / 9
73
+
74
+ ALL_READABILITY_CLI_FLAG_TOKENS: frozenset[str] = frozenset(
75
+ {
76
+ "--readability-loosen",
77
+ "--readability-reset",
78
+ "--readability-disable",
79
+ "--readability-enable",
80
+ }
81
+ )
82
+
83
+ FLESCH_BASE_SCORE: float = 206.835
84
+ FLESCH_WORDS_PER_SENTENCE_COEFFICIENT: float = 1.015
85
+ FLESCH_SYLLABLES_PER_WORD_COEFFICIENT: float = 84.6
86
+ FLESCH_PERFECT_SCORE: float = 100.0
87
+
88
+ READABILITY_STATE_FILE: Path = Path.home() / ".claude" / "state" / "pr_description_readability_strikes.json"
89
+ READABILITY_THRESHOLD_OVERRIDE_FILE: Path = (
90
+ Path.home() / ".claude" / "state" / "pr_description_readability_overrides.json"
91
+ )
92
+ READABILITY_ENABLED_STATE_FILE: Path = (
93
+ Path.home() / ".claude" / "state" / "pr_description_readability_enabled.json"
94
+ )
95
+
96
+
97
+ @dataclass(frozen=True)
98
+ class ReadabilityThresholds:
99
+ """Three readability thresholds carried as a single typed structure."""
100
+
101
+ flesch_min: int
102
+ max_sentence_words: int
103
+ avg_sentence_words: int
104
+
105
+
106
+ DEFAULT_READABILITY_THRESHOLDS: ReadabilityThresholds = ReadabilityThresholds(
107
+ flesch_min=READABILITY_MIN_FLESCH,
108
+ max_sentence_words=READABILITY_MAX_SENTENCE_WORDS,
109
+ avg_sentence_words=READABILITY_AVG_SENTENCE_WORDS,
110
+ )
111
+
112
+
113
+ __all__ = [
114
+ "ALL_HEAVY_OPENING_HEADERS",
115
+ "ALL_HEAVY_TESTING_HEADERS",
116
+ "ALL_READABILITY_CLI_FLAG_TOKENS",
117
+ "ATOMIC_WRITE_TEMP_SUFFIX",
118
+ "BLOCKQUOTE_MARKER_PATTERN",
119
+ "BOLD_PAIR_PATTERN",
120
+ "BULLET_MARKER_PATTERN",
121
+ "DEFAULT_READABILITY_THRESHOLDS",
122
+ "FENCED_CODE_BLOCK_PATTERN",
123
+ "FLESCH_BASE_SCORE",
124
+ "FLESCH_PERFECT_SCORE",
125
+ "FLESCH_SYLLABLES_PER_WORD_COEFFICIENT",
126
+ "FLESCH_WORDS_PER_SENTENCE_COEFFICIENT",
127
+ "GH_PR_COMMAND_MIN_TOKEN_COUNT",
128
+ "HEADING_LINE_PATTERN",
129
+ "HEAVY_MIN_BODY_CHARS_FOR_CLASSIFICATION",
130
+ "HEAVY_SHAPE",
131
+ "INLINE_CODE_PATTERN",
132
+ "LINK_TEXT_PATTERN",
133
+ "MINIMUM_SUBSTANTIVE_PROSE_CHARS",
134
+ "PR_GUIDE_PATH",
135
+ "READABILITY_AVG_SENTENCE_WORDS_CEILING",
136
+ "READABILITY_ENABLED_STATE_FILE",
137
+ "READABILITY_FLESCH_LOOSEN_FACTOR",
138
+ "READABILITY_LOOSEN_CAP",
139
+ "READABILITY_MAX_SENTENCE_WORDS_CEILING",
140
+ "READABILITY_MIN_FLESCH_FLOOR",
141
+ "READABILITY_SENTENCE_WORDS_LOOSEN_FACTOR",
142
+ "READABILITY_STATE_FILE",
143
+ "READABILITY_STRIKE_THRESHOLD",
144
+ "READABILITY_THRESHOLD_OVERRIDE_FILE",
145
+ "ReadabilityThresholds",
146
+ "SELF_CLOSING_REFERENCE_MESSAGE_PREFIX",
147
+ "SELF_CLOSING_REFERENCE_MESSAGE_SUFFIX",
148
+ "SELF_REFERENCE_PATTERN_TEMPLATE",
149
+ "STANDARD_SHAPE",
150
+ "THIS_PR_OPENING_PATTERN",
151
+ "TRIVIAL_BODY_CHAR_THRESHOLD",
152
+ "TRIVIAL_SHAPE",
153
+ "WHITESPACE_RUN_PATTERN",
154
+ ]
@@ -5,7 +5,7 @@ from __future__ import annotations
5
5
  import json
6
6
  import sys
7
7
 
8
- from config.setup_project_paths_constants import (
8
+ from hooks_constants.setup_project_paths_constants import (
9
9
  DECODE_ERRORS_POLICY,
10
10
  UTF8_BYTE_ORDER_MARK,
11
11
  UTF8_ENCODING,
@@ -7,8 +7,8 @@ import logging
7
7
  import os
8
8
  from pathlib import Path
9
9
 
10
- from config.dynamic_stderr_handler import DynamicStderrHandler
11
- from config.setup_project_paths_constants import META_KEY, UTF8_ENCODING
10
+ from hooks_constants.dynamic_stderr_handler import DynamicStderrHandler
11
+ from hooks_constants.setup_project_paths_constants import META_KEY, UTF8_ENCODING
12
12
 
13
13
 
14
14
  _logger = logging.getLogger("project_paths_reader")
@@ -9,7 +9,7 @@ _HOOKS_ROOT = Path(__file__).resolve().parent.parent
9
9
  if str(_HOOKS_ROOT) not in sys.path:
10
10
  sys.path.insert(0, str(_HOOKS_ROOT))
11
11
 
12
- from config.banned_identifiers_constants import (
12
+ from hooks_constants.banned_identifiers_constants import (
13
13
  ALL_BANNED_IDENTIFIERS,
14
14
  BANNED_IDENTIFIER_MESSAGE_SUFFIX,
15
15
  BANNED_IDENTIFIER_SKIP_ADVISORY,
@@ -12,7 +12,7 @@ _HOOKS_ROOT = Path(__file__).resolve().parent.parent
12
12
  if str(_HOOKS_ROOT) not in sys.path:
13
13
  sys.path.insert(0, str(_HOOKS_ROOT))
14
14
 
15
- from config.dynamic_stderr_handler import DynamicStderrHandler
15
+ from hooks_constants.dynamic_stderr_handler import DynamicStderrHandler
16
16
 
17
17
 
18
18
  def _make_logger_with_handler() -> tuple[logging.Logger, DynamicStderrHandler]:
@@ -9,7 +9,7 @@ _HOOKS_ROOT = Path(__file__).resolve().parent.parent
9
9
  if str(_HOOKS_ROOT) not in sys.path:
10
10
  sys.path.insert(0, str(_HOOKS_ROOT))
11
11
 
12
- from config.hardcoded_user_path_constants import HARDCODED_USER_PATH_PATTERN
12
+ from hooks_constants.hardcoded_user_path_constants import HARDCODED_USER_PATH_PATTERN
13
13
 
14
14
 
15
15
  def test_pattern_matches_windows_user_home() -> None:
@@ -10,8 +10,8 @@ _HOOKS_ROOT = Path(__file__).resolve().parent.parent
10
10
  if str(_HOOKS_ROOT) not in sys.path:
11
11
  sys.path.insert(0, str(_HOOKS_ROOT))
12
12
 
13
- from config import hook_log_extractor_constants
14
- from config.hook_log_extractor_constants import (
13
+ from hooks_constants import hook_log_extractor_constants
14
+ from hooks_constants.hook_log_extractor_constants import (
15
15
  EXIT_CODE_ENVIRONMENT_MISSING,
16
16
  EXIT_CODE_EXTRACTOR_ENVIRONMENT_MISSING,
17
17
  EXIT_CODE_SUCCESS,