claude-dev-env 1.42.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 (207) hide show
  1. package/_shared/pr-loop/scripts/_claude_permissions_common.py +1 -5
  2. package/_shared/pr-loop/scripts/code_rules_gate.py +293 -8
  3. package/_shared/pr-loop/scripts/fix_hookspath.py +96 -5
  4. package/_shared/pr-loop/scripts/grant_project_claude_permissions.py +3 -16
  5. package/_shared/pr-loop/scripts/post_audit_thread.py +4 -4
  6. package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/claude_permissions_constants.py +1 -1
  7. package/_shared/pr-loop/scripts/preflight.py +13 -31
  8. package/_shared/pr-loop/scripts/reviews_disabled.py +2 -16
  9. package/_shared/pr-loop/scripts/revoke_project_claude_permissions.py +3 -16
  10. package/_shared/pr-loop/scripts/tests/conftest.py +1 -51
  11. package/_shared/pr-loop/scripts/tests/test_agent_config_carveout.py +4 -4
  12. package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +4 -2
  13. package/_shared/pr-loop/scripts/tests/test_claude_permissions_constants.py +4 -2
  14. package/_shared/pr-loop/scripts/tests/test_claude_settings_keys_constants.py +4 -2
  15. package/_shared/pr-loop/scripts/tests/test_code_rules_gate_constants.py +4 -2
  16. package/_shared/pr-loop/scripts/tests/test_fix_hookspath_constants.py +6 -2
  17. package/_shared/pr-loop/scripts/tests/test_grant_project_claude_permissions.py +2 -2
  18. package/_shared/pr-loop/scripts/tests/test_post_audit_thread.py +1 -2
  19. package/_shared/pr-loop/scripts/tests/test_post_audit_thread_constants.py +4 -2
  20. package/_shared/pr-loop/scripts/tests/test_preflight.py +17 -52
  21. package/_shared/pr-loop/scripts/tests/test_preflight_constants.py +6 -2
  22. package/_shared/pr-loop/scripts/tests/test_revoke_project_claude_permissions.py +2 -2
  23. package/agents/pr-description-writer.md +50 -140
  24. package/docs/PR_DESCRIPTION_GUIDE.md +101 -102
  25. package/hooks/_gh_pr_author_swap_utils.py +1 -1
  26. package/hooks/blocking/bot_mention_comment_blocker.py +4 -10
  27. package/hooks/blocking/code_rules_enforcer.py +217 -99
  28. package/hooks/blocking/code_rules_path_utils.py +8 -1
  29. package/hooks/blocking/destructive_command_blocker.py +1 -1
  30. package/hooks/blocking/es_exe_path_rewriter.py +7 -13
  31. package/hooks/blocking/gh_body_arg_blocker.py +6 -1
  32. package/hooks/blocking/gh_pr_author_enforcer.py +5 -5
  33. package/hooks/blocking/gh_pr_author_restore.py +5 -5
  34. package/hooks/blocking/hedging_language_blocker.py +4 -10
  35. package/hooks/blocking/md_path_exemptions.py +205 -0
  36. package/hooks/blocking/md_to_html_blocker.py +48 -20
  37. package/hooks/blocking/pr_converge_bugteam_enforcer.py +5 -11
  38. package/hooks/blocking/pr_description_enforcer.py +626 -41
  39. package/hooks/blocking/question_to_user_enforcer.py +4 -10
  40. package/hooks/blocking/state_description_blocker.py +6 -12
  41. package/hooks/blocking/tdd_enforcer.py +1 -1
  42. package/hooks/blocking/test_bot_mention_comment_blocker.py +1 -1
  43. package/hooks/blocking/test_code_rules_enforcer.py +3 -3
  44. package/hooks/blocking/test_code_rules_enforcer_any_exempt_files.py +1 -1
  45. package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +0 -2
  46. package/hooks/blocking/test_code_rules_enforcer_comment_string_awareness.py +184 -0
  47. package/hooks/blocking/test_code_rules_enforcer_type_checking_scope.py +82 -0
  48. package/hooks/blocking/test_code_rules_enforcer_unused_imports.py +29 -29
  49. package/hooks/blocking/test_gh_body_arg_blocker.py +7 -8
  50. package/hooks/blocking/test_gh_pr_author_enforcer.py +1 -1
  51. package/hooks/blocking/test_gh_pr_author_restore.py +1 -1
  52. package/hooks/blocking/test_hedging_language_blocker.py +2 -2
  53. package/hooks/blocking/test_md_to_html_blocker.py +463 -8
  54. package/hooks/blocking/test_pr_converge_bugteam_enforcer.py +1 -1
  55. package/hooks/blocking/test_pr_description_enforcer.py +1210 -13
  56. package/hooks/blocking/test_question_to_user_enforcer.py +1 -1
  57. package/hooks/blocking/windows_rmtree_blocker.py +5 -11
  58. package/hooks/diagnostic/hook_log_extractor.py +1 -1
  59. package/hooks/diagnostic/hook_log_init.py +1 -1
  60. package/hooks/diagnostic/hook_log_stop_wrapper.py +1 -1
  61. package/hooks/diagnostic/test_hook_log_extractor.py +1 -1
  62. package/hooks/diagnostic/test_hook_log_init.py +2 -2
  63. package/hooks/diagnostic/test_hook_log_stop_wrapper.py +1 -1
  64. package/hooks/git-hooks/gate_utils.py +1 -1
  65. package/hooks/git-hooks/pre_commit.py +1 -1
  66. package/hooks/git-hooks/pre_push.py +1 -1
  67. package/hooks/git-hooks/test_config.py +5 -5
  68. package/hooks/git-hooks/test_pre_push.py +6 -6
  69. package/hooks/{config → hooks_constants}/code_rules_enforcer_constants.py +37 -0
  70. package/hooks/hooks_constants/code_rules_path_utils_constants.py +28 -0
  71. package/hooks/hooks_constants/md_to_html_blocker_constants.py +82 -0
  72. package/hooks/{config → hooks_constants}/pr_converge_bugteam_enforcer_state.py +1 -1
  73. package/hooks/hooks_constants/pr_description_enforcer_constants.py +154 -0
  74. package/hooks/{config → hooks_constants}/pre_tool_use_stdin.py +1 -1
  75. package/hooks/{config → hooks_constants}/project_paths_reader.py +2 -2
  76. package/hooks/{config → hooks_constants}/test_banned_identifiers_constants.py +1 -1
  77. package/hooks/{config → hooks_constants}/test_dynamic_stderr_handler.py +1 -1
  78. package/hooks/{config → hooks_constants}/test_hardcoded_user_path_constants.py +1 -1
  79. package/hooks/{config → hooks_constants}/test_hook_log_extractor_constants.py +2 -2
  80. package/hooks/hooks_constants/test_md_to_html_blocker_constants.py +110 -0
  81. package/hooks/{config → hooks_constants}/test_messages.py +2 -6
  82. package/hooks/{config → hooks_constants}/test_path_rewriter_constants.py +1 -1
  83. package/hooks/hooks_constants/test_pr_description_enforcer_constants.py +292 -0
  84. package/hooks/{config → hooks_constants}/test_pre_tool_use_stdin.py +2 -2
  85. package/hooks/{config → hooks_constants}/test_project_paths_reader.py +3 -3
  86. package/hooks/{config → hooks_constants}/test_session_env_cleanup_constants.py +1 -1
  87. package/hooks/{config → hooks_constants}/test_setup_project_paths_constants.py +2 -2
  88. package/hooks/{config → hooks_constants}/test_unused_module_import_constants.py +1 -1
  89. package/hooks/lifecycle/pr_converge_bugteam_skill_tracker.py +5 -11
  90. package/hooks/lifecycle/test_pr_converge_bugteam_skill_tracker.py +1 -1
  91. package/hooks/session/gh_pr_author_session_cleanup.py +5 -6
  92. package/hooks/session/session_env_cleanup.py +4 -10
  93. package/hooks/session/test_gh_pr_author_session_cleanup.py +1 -1
  94. package/hooks/session/test_untracked_repo_detector.py +2 -2
  95. package/hooks/session/untracked_repo_detector.py +6 -12
  96. package/hooks/test__gh_pr_author_swap_utils.py +1 -1
  97. package/hooks/validators/run_all_validators.py +16 -5
  98. package/hooks/validators/test_output_formatter.py +46 -0
  99. package/hooks/workflow/doc_gist_auto_publish.py +1 -1
  100. package/hooks/workflow/md_to_html_companion.py +8 -15
  101. package/hooks/workflow/test_md_to_html_companion.py +184 -23
  102. package/package.json +1 -1
  103. package/rules/ask-user-question-required.md +1 -1
  104. package/rules/vault-context.md +1 -1
  105. package/scripts/{config → dev_env_scripts_constants}/timing.py +1 -1
  106. package/scripts/setup_project_paths.py +49 -11
  107. package/scripts/sweep_empty_dirs.py +10 -1
  108. package/scripts/test_setup_project_paths.py +2 -2
  109. package/scripts/test_sweep_empty_dirs.py +2 -6
  110. package/skills/_shared/pr-loop/scripts/_path_resolver.py +1 -1
  111. package/skills/_shared/pr-loop/scripts/build_audit_prompt.py +1 -1
  112. package/skills/_shared/pr-loop/scripts/build_fix_prompt.py +1 -1
  113. package/skills/_shared/pr-loop/scripts/init_loop_state.py +1 -1
  114. package/skills/_shared/pr-loop/scripts/teardown_worktrees.py +1 -1
  115. package/skills/_shared/pr-loop/scripts/write_audit_outcomes.py +2 -2
  116. package/skills/_shared/pr-loop/scripts/write_fix_outcomes.py +2 -2
  117. package/skills/bugteam/PROMPTS.md +1 -1
  118. package/skills/bugteam/SKILL.md +1 -1
  119. package/skills/bugteam/reference/github-pr-reviews.md +1 -1
  120. package/skills/bugteam/scripts/{_claude_permissions_common.py → _bugteam_permissions_common.py} +1 -13
  121. package/skills/bugteam/scripts/bugteam_code_rules_gate.py +1 -13
  122. package/skills/bugteam/scripts/bugteam_fix_hookspath.py +1 -16
  123. package/skills/bugteam/scripts/bugteam_preflight.py +1 -13
  124. package/skills/bugteam/scripts/grant_project_claude_permissions.py +2 -8
  125. package/skills/bugteam/scripts/probe_code_rules_enforcer_check.py +1 -1
  126. package/skills/bugteam/scripts/reflow_skill_md.py +1 -1
  127. package/skills/bugteam/scripts/revoke_project_claude_permissions.py +2 -8
  128. package/skills/bugteam/scripts/{test__claude_permissions_common.py → test__bugteam_permissions_common.py} +4 -4
  129. package/skills/bugteam/scripts/test_agent_config_carveout.py +2 -2
  130. package/skills/bugteam/scripts/test_bugteam_fix_hookspath.py +0 -26
  131. package/skills/bugteam/scripts/{test_claude_permissions_common.py → test_bugteam_permissions_common.py} +3 -66
  132. package/skills/bugteam/scripts/test_bugteam_preflight.py +2 -27
  133. package/skills/bugteam/scripts/windows_safe_rmtree.py +1 -1
  134. package/skills/doc-gist/SKILL.md +1 -1
  135. package/skills/doc-gist/scripts/gist_upload.py +1 -1
  136. package/skills/implement/SKILL.md +2 -2
  137. package/skills/implement/scripts/append_note.py +1 -1
  138. package/skills/pr-converge/pr_converge_skill_constants/__init__.py +0 -0
  139. package/skills/pr-converge/{config → pr_converge_skill_constants}/constants.py +1 -1
  140. package/skills/pr-converge/scripts/check_bugbot_ci.py +1 -1
  141. package/skills/pr-converge/scripts/check_convergence.py +11 -4
  142. package/skills/pr-converge/scripts/check_pending_reviews.py +1 -1
  143. package/skills/pr-converge/scripts/fetch_copilot_reviews.py +1 -1
  144. package/skills/pr-converge/scripts/post_fix_reply.py +1 -1
  145. package/skills/pr-converge/scripts/pr_converge_scripts_constants/__init__.py +0 -0
  146. package/skills/pr-converge/scripts/{config → pr_converge_scripts_constants}/pr_converge_constants.py +1 -1
  147. package/skills/pr-converge/scripts/reflow_skill_md.py +90 -16
  148. package/skills/pr-converge/scripts/test_check_convergence.py +18 -0
  149. package/skills/pr-converge/scripts/test_reflow_skill_md.py +0 -31
  150. package/skills/session-log/SKILL.md +98 -233
  151. package/hooks/config/pr_description_enforcer_constants.py +0 -19
  152. package/hooks/config/test_pr_description_enforcer_constants.py +0 -82
  153. package/skills/bugteam/scripts/test_grant_project_claude_permissions.py +0 -55
  154. package/skills/bugteam/scripts/test_revoke_project_claude_permissions.py +0 -55
  155. package/skills/pr-converge/scripts/conftest.py +0 -60
  156. package/skills/pr-converge/scripts/evict_cached_config_modules.py +0 -20
  157. package/skills/pr-converge/scripts/test_evict_cached_config_modules.py +0 -22
  158. /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/__init__.py +0 -0
  159. /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/claude_settings_keys_constants.py +0 -0
  160. /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/code_rules_gate_constants.py +0 -0
  161. /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/fix_hookspath_constants.py +0 -0
  162. /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/post_audit_thread_constants.py +0 -0
  163. /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/preflight_constants.py +0 -0
  164. /package/_shared/pr-loop/scripts/{config → pr_loop_shared_constants}/reviews_disabled_constants.py +0 -0
  165. /package/hooks/git-hooks/{config.py → git_hooks_constants/__init__.py} +0 -0
  166. /package/hooks/{config → hooks_constants}/__init__.py +0 -0
  167. /package/hooks/{config → hooks_constants}/any_type_config.py +0 -0
  168. /package/hooks/{config → hooks_constants}/banned_identifiers_constants.py +0 -0
  169. /package/hooks/{config → hooks_constants}/blocking_check_limits.py +0 -0
  170. /package/hooks/{config → hooks_constants}/bot_mention_comment_blocker_constants.py +0 -0
  171. /package/hooks/{config → hooks_constants}/convergence_branch_constants.py +0 -0
  172. /package/hooks/{config → hooks_constants}/doc_gist_auto_publish_constants.py +0 -0
  173. /package/hooks/{config → hooks_constants}/dynamic_stderr_handler.py +0 -0
  174. /package/hooks/{config → hooks_constants}/gh_pr_author_swap_constants.py +0 -0
  175. /package/hooks/{config → hooks_constants}/hardcoded_user_path_constants.py +0 -0
  176. /package/hooks/{config → hooks_constants}/hook_log_extractor_constants.py +0 -0
  177. /package/hooks/{config → hooks_constants}/html_companion_constants.py +0 -0
  178. /package/hooks/{config → hooks_constants}/inline_tuple_string_magic_constants.py +0 -0
  179. /package/hooks/{config → hooks_constants}/messages.py +0 -0
  180. /package/hooks/{config → hooks_constants}/path_rewriter_constants.py +0 -0
  181. /package/hooks/{config → hooks_constants}/pr_converge_bugteam_enforcer_constants.py +0 -0
  182. /package/hooks/{config → hooks_constants}/session_env_cleanup_constants.py +0 -0
  183. /package/hooks/{config → hooks_constants}/setup_project_paths_constants.py +0 -0
  184. /package/hooks/{config → hooks_constants}/state_description_blocker_constants.py +0 -0
  185. /package/hooks/{config → hooks_constants}/stuttering_check_config.py +0 -0
  186. /package/hooks/{config → hooks_constants}/stuttering_import_binding_constants.py +0 -0
  187. /package/hooks/{config → hooks_constants}/sys_path_insert_constants.py +0 -0
  188. /package/hooks/{config → hooks_constants}/unused_module_import_constants.py +0 -0
  189. /package/hooks/{config → hooks_constants}/windows_rmtree_blocker_constants.py +0 -0
  190. /package/{skills/_shared/pr-loop/scripts/config → hooks/lifecycle}/__init__.py +0 -0
  191. /package/{skills/bugteam/scripts/config → hooks/session}/__init__.py +0 -0
  192. /package/scripts/{config → dev_env_scripts_constants}/__init__.py +0 -0
  193. /package/skills/{doc-gist/scripts/config → _shared/pr-loop/scripts/skills_pr_loop_constants}/__init__.py +0 -0
  194. /package/skills/_shared/pr-loop/scripts/{config → skills_pr_loop_constants}/path_resolver_constants.py +0 -0
  195. /package/skills/{implement/scripts/config → bugteam/scripts/bugteam_scripts_constants}/__init__.py +0 -0
  196. /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/bugteam_code_rules_gate_constants.py +0 -0
  197. /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/bugteam_fix_hookspath_constants.py +0 -0
  198. /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/bugteam_preflight_constants.py +0 -0
  199. /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/claude_permissions_common_constants.py +0 -0
  200. /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/probe_code_rules_enforcer_check_constants.py +0 -0
  201. /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/reflow_skill_md_constants.py +0 -0
  202. /package/skills/bugteam/scripts/{config → bugteam_scripts_constants}/windows_safe_rmtree_constants.py +0 -0
  203. /package/skills/{pr-converge/config → doc-gist/scripts/doc_gist_scripts_constants}/__init__.py +0 -0
  204. /package/skills/doc-gist/scripts/{config → doc_gist_scripts_constants}/gist_upload_constants.py +0 -0
  205. /package/skills/{pr-converge/scripts/config → implement/scripts/implement_scripts_constants}/__init__.py +0 -0
  206. /package/skills/implement/scripts/{config → implement_scripts_constants}/notes_constants.py +0 -0
  207. /package/skills/pr-converge/scripts/{config → pr_converge_scripts_constants}/reflow_skill_md_constants.py +0 -0
@@ -16,7 +16,7 @@ import os
16
16
  import sys
17
17
  import time
18
18
 
19
- from config.timing import DEFAULT_AGE_SECONDS, DEFAULT_POLL_INTERVAL
19
+ from dev_env_scripts_constants.timing import DEFAULT_AGE_SECONDS, DEFAULT_POLL_INTERVAL
20
20
 
21
21
 
22
22
  def _positive_int(raw_argument: str) -> int:
@@ -42,6 +42,15 @@ def sweep(root: str, min_age_seconds: int) -> list[str]:
42
42
  Walks bottom-up so nested empty directories are cleaned from the leaves
43
43
  inward. Relies on os.rmdir to fail harmlessly for non-empty directories
44
44
  instead of checking snapshotted subdirectory lists.
45
+
46
+ Args:
47
+ root: Root directory to walk; directories below the root are
48
+ candidates for removal.
49
+ min_age_seconds: Minimum age in seconds for a directory to qualify
50
+ for removal.
51
+
52
+ Returns:
53
+ Sorted list of directory paths that were removed during the sweep.
45
54
  """
46
55
 
47
56
  all_removed: list[str] = []
@@ -22,8 +22,8 @@ for each_sys_path_entry in (
22
22
 
23
23
  import setup_project_paths as setup
24
24
  import untracked_repo_detector as detector_module
25
- from config.project_paths_reader import registry_file_path
26
- from config.setup_project_paths_constants import (
25
+ from hooks_constants.project_paths_reader import registry_file_path
26
+ from hooks_constants.setup_project_paths_constants import (
27
27
  ABORTED_NOTHING_WRITTEN_MESSAGE,
28
28
  CONFIRMATION_PROMPT_TEXT,
29
29
  ES_EXE_FOLDERS_ONLY_QUERY_ARGUMENTS,
@@ -15,10 +15,6 @@ _SCRIPTS_DIR = Path(os.path.abspath(__file__)).parent
15
15
  if str(_SCRIPTS_DIR) not in sys.path:
16
16
  sys.path.insert(0, str(_SCRIPTS_DIR))
17
17
 
18
- for _cached in list(sys.modules):
19
- if _cached == "config" or _cached.startswith("config."):
20
- del sys.modules[_cached]
21
-
22
18
  from sweep_empty_dirs import _build_parser, _positive_int, sweep # noqa: E402
23
19
 
24
20
  _OLD_TIMESTAMP = time.time() - 300
@@ -53,7 +49,7 @@ def test_positive_int_rejects_non_integer() -> None:
53
49
 
54
50
 
55
51
  def test_build_parser_sets_age_default_from_timing_config() -> None:
56
- """_build_parser uses DEFAULT_AGE_SECONDS from config.timing as --age default."""
52
+ """_build_parser uses DEFAULT_AGE_SECONDS from dev_env_scripts_constants.timing as --age default."""
57
53
  parser = _build_parser()
58
54
  default_age = parser.get_default("age")
59
55
  assert isinstance(default_age, int)
@@ -61,7 +57,7 @@ def test_build_parser_sets_age_default_from_timing_config() -> None:
61
57
 
62
58
 
63
59
  def test_build_parser_sets_interval_default_from_timing_config() -> None:
64
- """_build_parser uses DEFAULT_POLL_INTERVAL from config.timing as --interval default."""
60
+ """_build_parser uses DEFAULT_POLL_INTERVAL from dev_env_scripts_constants.timing as --interval default."""
65
61
  parser = _build_parser()
66
62
  default_interval = parser.get_default("interval")
67
63
  assert isinstance(default_interval, int)
@@ -9,7 +9,7 @@ from __future__ import annotations
9
9
  import tempfile
10
10
  from pathlib import Path
11
11
 
12
- from config.path_resolver_constants import (
12
+ from skills_pr_loop_constants.path_resolver_constants import (
13
13
  DIFF_PATCH_TEMPLATE,
14
14
  FIX_OUTCOME_XML_TEMPLATE,
15
15
  MULTI_PR_SLUG_TEMPLATE,
@@ -19,7 +19,7 @@ if str(_self_dir) not in sys.path:
19
19
  sys.path.insert(0, str(_self_dir))
20
20
 
21
21
  from _xml_utils import emit_pretty_xml
22
- from config.path_resolver_constants import (
22
+ from skills_pr_loop_constants.path_resolver_constants import (
23
23
  ALL_AUDIT_CATEGORY_ENTRIES,
24
24
  ALL_AUDIT_CONSTRAINT_TEXTS,
25
25
  )
@@ -21,7 +21,7 @@ if str(_self_dir) not in sys.path:
21
21
 
22
22
  from _cli_utils import require_file
23
23
  from _xml_utils import emit_pretty_xml
24
- from config.path_resolver_constants import (
24
+ from skills_pr_loop_constants.path_resolver_constants import (
25
25
  ALL_FIX_CONSTRAINT_TEXTS,
26
26
  ALL_FIX_EXECUTION_STEPS,
27
27
  )
@@ -20,7 +20,7 @@ from _path_resolver import (
20
20
  per_pr_workspace,
21
21
  resolve_run_temp_dir,
22
22
  )
23
- from config.path_resolver_constants import LOOP_STATE_JSON_INDENT
23
+ from skills_pr_loop_constants.path_resolver_constants import LOOP_STATE_JSON_INDENT
24
24
 
25
25
 
26
26
  def create_loop_state(
@@ -24,7 +24,7 @@ if str(_self_dir) not in sys.path:
24
24
  sys.path.insert(0, str(_self_dir))
25
25
 
26
26
  from _path_resolver import per_pr_workspace
27
- from config.path_resolver_constants import ALL_PYTHON_ONEXC_VERSION
27
+ from skills_pr_loop_constants.path_resolver_constants import ALL_PYTHON_ONEXC_VERSION
28
28
 
29
29
 
30
30
  def _remove_readonly_attribute(
@@ -19,7 +19,7 @@ if str(_self_dir) not in sys.path:
19
19
  from _cli_utils import require_file
20
20
  from _path_resolver import outcome_xml_path
21
21
  from _xml_utils import emit_pretty_xml
22
- from config.path_resolver_constants import ALL_FINDING_BODY_ELEMENT_KEYS
22
+ from skills_pr_loop_constants.path_resolver_constants import ALL_FINDING_BODY_ELEMENT_KEYS
23
23
 
24
24
 
25
25
  def build_audit_xml(
@@ -70,7 +70,7 @@ def _populate_findings(parent: Element, findings_data: list[dict[str, object]])
70
70
 
71
71
  Scalar finding fields become XML attributes on `<finding>`; the
72
72
  body fields named in `ALL_FINDING_BODY_ELEMENT_KEYS` (defined in
73
- `packages/claude-dev-env/skills/_shared/pr-loop/scripts/config/path_resolver_constants.py`
73
+ `packages/claude-dev-env/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py`
74
74
  and currently `("title", "excerpt", "description")`) become child elements.
75
75
  Nested dicts or lists in scalar slots are flattened to string form
76
76
  so attribute serialization stays well-defined.
@@ -1,7 +1,7 @@
1
1
  """Validate status enum values and write <bugteam_fix> XML at the canonical path.
2
2
 
3
3
  Status enum (canonical source: `ALL_VALID_FIX_STATUSES` in
4
- `packages/claude-dev-env/skills/_shared/pr-loop/scripts/config/path_resolver_constants.py`):
4
+ `packages/claude-dev-env/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py`):
5
5
  fixed | could_not_address | hook_blocked | unverified_fixed.
6
6
 
7
7
  Each outcome's scalar fields become XML attributes on `<outcome>`; the
@@ -27,7 +27,7 @@ if str(_self_dir) not in sys.path:
27
27
  from _cli_utils import require_file
28
28
  from _path_resolver import fix_outcome_xml_path
29
29
  from _xml_utils import emit_pretty_xml
30
- from config.path_resolver_constants import (
30
+ from skills_pr_loop_constants.path_resolver_constants import (
31
31
  ALL_FIX_OUTCOME_BODY_ELEMENT_KEYS,
32
32
  ALL_VALID_FIX_STATUSES,
33
33
  )
@@ -108,7 +108,7 @@ cd into `<worktree_path>` before any git or file operation.
108
108
  teammate does NOT author the inline-comment body directly:
109
109
  `post_audit_thread.py` renders every body from
110
110
  `INLINE_COMMENT_BODY_TEMPLATE` (defined in
111
- [`_shared/pr-loop/scripts/config/post_audit_thread_constants.py`](../../_shared/pr-loop/scripts/config/post_audit_thread_constants.py))
111
+ [`_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py`](../../_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py))
112
112
  — the template prepends `**[<severity>] <Skill> audit finding**`
113
113
  and renders the suggested-fix block, so a teammate who hand-formats
114
114
  a title or footer wastes the work.
@@ -103,7 +103,7 @@ narrative) becomes `description`, and the suffix starting at `Fix:`
103
103
  When the agent omits the `Fix:` heading on a given finding, write the
104
104
  full `failure_mode` text to BOTH `description` and `fix_summary` so the
105
105
  script's body template (`INLINE_COMMENT_BODY_TEMPLATE` in
106
- [`_shared/pr-loop/scripts/config/post_audit_thread_constants.py`](../../_shared/pr-loop/scripts/config/post_audit_thread_constants.py))
106
+ [`_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py`](../../_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py))
107
107
  still renders coherently. Set `side="RIGHT"` for every entry. On CLEAN,
108
108
  pass an empty array (`[]`) so the script posts an APPROVE review
109
109
  (GitHub stores it as `state=APPROVED`) with a "no findings" summary and
@@ -22,7 +22,7 @@ python "${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/post_audit_thread.py"
22
22
 
23
23
  Capture `<head_sha>` via `git rev-parse HEAD` in the subagent cwd immediately before this call so the review attaches to the commit the audit actually scoped.
24
24
 
25
- `--findings-json` points to a JSON file whose root is a list of objects shaped `{path, line, side, severity, description, fix_summary}`. Build it from the merged Shape A findings: finding `file` → `path`. Each finding's `failure_mode` carries the full audit-to-fix handoff text per [`agents/code-quality-agent.md`](../../../agents/code-quality-agent.md); split `failure_mode` at the literal `Fix:` heading so the failure narrative becomes `description` and the suffix beginning at `Fix:` (including the trailing `Validation:` clause) becomes `fix_summary`. When a finding's `failure_mode` omits the `Fix:` heading, write the full text to BOTH `description` and `fix_summary` so the script's body template (`INLINE_COMMENT_BODY_TEMPLATE` in [`packages/claude-dev-env/_shared/pr-loop/scripts/config/post_audit_thread_constants.py`](../../../_shared/pr-loop/scripts/config/post_audit_thread_constants.py)) renders coherently. Set `side="RIGHT"` for every entry. On CLEAN the list is empty (`[]`); on DIRTY the list carries one entry per finding.
25
+ `--findings-json` points to a JSON file whose root is a list of objects shaped `{path, line, side, severity, description, fix_summary}`. Build it from the merged Shape A findings: finding `file` → `path`. Each finding's `failure_mode` carries the full audit-to-fix handoff text per [`agents/code-quality-agent.md`](../../../agents/code-quality-agent.md); split `failure_mode` at the literal `Fix:` heading so the failure narrative becomes `description` and the suffix beginning at `Fix:` (including the trailing `Validation:` clause) becomes `fix_summary`. When a finding's `failure_mode` omits the `Fix:` heading, write the full text to BOTH `description` and `fix_summary` so the script's body template (`INLINE_COMMENT_BODY_TEMPLATE` in [`packages/claude-dev-env/_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py`](../../../_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py)) renders coherently. Set `side="RIGHT"` for every entry. On CLEAN the list is empty (`[]`); on DIRTY the list carries one entry per finding.
26
26
 
27
27
  The script handles retries internally — 1s / 4s / 16s backoff across four attempts (one initial plus three retries). Exit codes:
28
28
 
@@ -16,25 +16,13 @@ from collections.abc import Callable
16
16
  from pathlib import Path
17
17
  from typing import NoReturn
18
18
 
19
- _previously_cached_config = {}
20
- for each_cached_module_name in [
21
- each_module_key
22
- for each_module_key in list(sys.modules)
23
- if each_module_key == "config" or each_module_key.startswith("config.")
24
- ]:
25
- _previously_cached_config[each_cached_module_name] = sys.modules.pop(
26
- each_cached_module_name
27
- )
28
-
29
- from config.claude_permissions_common_constants import (
19
+ from bugteam_scripts_constants.claude_permissions_common_constants import (
30
20
  ALL_TRUST_ENTRY_PROJECT_PATH_BOUNDARY_QUOTE_CHARACTERS,
31
21
  ATOMIC_WRITE_TEMPORARY_SUFFIX,
32
22
  DEFAULT_SETTINGS_FILE_MODE,
33
23
  TEXT_FILE_ENCODING,
34
24
  )
35
25
 
36
- sys.modules.update(_previously_cached_config)
37
-
38
26
 
39
27
  def exit_with_error(message: str) -> NoReturn:
40
28
  print(f"Error: {message}", file=sys.stderr)
@@ -11,17 +11,7 @@ from pathlib import Path
11
11
 
12
12
  ValidateContentCallable = Callable[..., list[str]]
13
13
 
14
- _previously_cached_config = {}
15
- for each_cached_module_name in [
16
- each_module_key
17
- for each_module_key in list(sys.modules)
18
- if each_module_key == "config" or each_module_key.startswith("config.")
19
- ]:
20
- _previously_cached_config[each_cached_module_name] = sys.modules.pop(
21
- each_cached_module_name
22
- )
23
-
24
- from config.bugteam_code_rules_gate_constants import (
14
+ from bugteam_scripts_constants.bugteam_code_rules_gate_constants import (
25
15
  ALL_CODE_FILE_EXTENSIONS,
26
16
  ALL_COLUMN_MAGIC_FALSE_VALUES,
27
17
  ALL_GIT_DIFF_CACHED_ARGS,
@@ -34,8 +24,6 @@ from config.bugteam_code_rules_gate_constants import (
34
24
  VIOLATION_LINE_RAW_PATTERN,
35
25
  )
36
26
 
37
- sys.modules.update(_previously_cached_config)
38
-
39
27
 
40
28
  def hunk_header_pattern() -> re.Pattern[str]:
41
29
  return re.compile(HUNK_HEADER_RAW_PATTERN)
@@ -5,22 +5,7 @@ import subprocess
5
5
  import sys
6
6
  from pathlib import Path
7
7
 
8
- parent_directory = str(Path(__file__).resolve().parent)
9
- try:
10
- sys.path.remove(parent_directory)
11
- except ValueError:
12
- pass
13
- if parent_directory not in sys.path:
14
- sys.path.insert(0, parent_directory)
15
-
16
- for each_cached_module_name in [
17
- each_module_key
18
- for each_module_key in list(sys.modules)
19
- if each_module_key == "config" or each_module_key.startswith("config.")
20
- ]:
21
- sys.modules.pop(each_cached_module_name, None)
22
-
23
- from config.bugteam_fix_hookspath_constants import (
8
+ from bugteam_scripts_constants.bugteam_fix_hookspath_constants import (
24
9
  ALL_CANONICAL_HOOKS_DIRECTORY_COMPONENTS,
25
10
  ALL_GLOBAL_HOOKS_PATH_ARGUMENTS,
26
11
  ALL_HOME_ENV_VAR_NAMES,
@@ -6,19 +6,13 @@ import subprocess
6
6
  import sys
7
7
  from pathlib import Path
8
8
 
9
- for each_cached_module_name in [
10
- each_module_key
11
- for each_module_key in list(sys.modules)
12
- if each_module_key == "config" or each_module_key.startswith("config.")
13
- ]:
14
- sys.modules.pop(each_cached_module_name, None)
15
9
  _bugteam_scripts_directory = str(Path(__file__).absolute().parent)
16
10
  while _bugteam_scripts_directory in sys.path:
17
11
  sys.path.remove(_bugteam_scripts_directory)
18
12
  if _bugteam_scripts_directory not in sys.path:
19
13
  sys.path.insert(0, _bugteam_scripts_directory)
20
14
 
21
- from config.bugteam_preflight_constants import (
15
+ from bugteam_scripts_constants.bugteam_preflight_constants import (
22
16
  ALL_DISCOVERY_IGNORE_DIRECTORIES,
23
17
  ALL_GIT_CONFIG_HOOKS_PATH_ARGUMENTS,
24
18
  ALL_PRE_COMMIT_ARGUMENTS,
@@ -35,12 +29,6 @@ from config.bugteam_preflight_constants import (
35
29
  PYTEST_INI_FILENAME,
36
30
  )
37
31
 
38
- for each_cached_module_name in [
39
- each_module_key
40
- for each_module_key in list(sys.modules)
41
- if each_module_key == "config" or each_module_key.startswith("config.")
42
- ]:
43
- sys.modules.pop(each_cached_module_name, None)
44
32
  _shared_pr_loop_scripts_directory = (
45
33
  Path(__file__).absolute().parent
46
34
  / ".." / ".." / ".." / "_shared" / "pr-loop" / "scripts"
@@ -9,17 +9,11 @@ the changes applied. No-op when the entries already exist.
9
9
  import sys
10
10
  from pathlib import Path
11
11
 
12
- for each_cached_module_name in [
13
- each_module_key
14
- for each_module_key in list(sys.modules)
15
- if each_module_key == "config" or each_module_key.startswith("config.")
16
- ]:
17
- sys.modules.pop(each_cached_module_name, None)
18
12
  parent_directory = str(Path(__file__).resolve().parent)
19
13
  if parent_directory not in sys.path:
20
14
  sys.path.insert(0, parent_directory)
21
15
 
22
- from _claude_permissions_common import ( # noqa: E402
16
+ from _bugteam_permissions_common import ( # noqa: E402
23
17
  append_if_missing,
24
18
  build_agent_config_deny_rules,
25
19
  build_permission_rules,
@@ -32,7 +26,7 @@ from _claude_permissions_common import ( # noqa: E402
32
26
  remove_matching_entries_from_list,
33
27
  save_settings,
34
28
  )
35
- from config.claude_permissions_common_constants import ( # noqa: E402
29
+ from bugteam_scripts_constants.claude_permissions_common_constants import ( # noqa: E402
36
30
  ALL_AGENT_CONFIG_DENY_TOOLS,
37
31
  ALL_AGENT_CONFIG_PATH_PATTERNS,
38
32
  ALL_PERMISSION_ALLOW_TOOLS,
@@ -19,7 +19,7 @@ import sys
19
19
  from pathlib import Path
20
20
  from types import ModuleType
21
21
 
22
- from config.probe_code_rules_enforcer_check_constants import (
22
+ from bugteam_scripts_constants.probe_code_rules_enforcer_check_constants import (
23
23
  DEFAULT_REPORTED_PATH,
24
24
  ENFORCER_MODULE_NAME,
25
25
  ENFORCER_RELATIVE_PATH,
@@ -18,7 +18,7 @@ from __future__ import annotations
18
18
  import re
19
19
  import textwrap
20
20
 
21
- from config.reflow_skill_md_constants import (
21
+ from bugteam_scripts_constants.reflow_skill_md_constants import (
22
22
  BASH_CONTINUATION_MARKER_WIDTH,
23
23
  BULLET_LIST_ITEM_PATTERN as BULLET_RE,
24
24
  MAXIMUM_LINE_WIDTH as MAX_WIDTH,
@@ -10,17 +10,11 @@ autoMode sections so repeated grant/revoke cycles leave no dead structure.
10
10
  import sys
11
11
  from pathlib import Path
12
12
 
13
- for each_cached_module_name in [
14
- each_module_key
15
- for each_module_key in list(sys.modules)
16
- if each_module_key == "config" or each_module_key.startswith("config.")
17
- ]:
18
- sys.modules.pop(each_cached_module_name, None)
19
13
  parent_directory = str(Path(__file__).resolve().parent)
20
14
  if parent_directory not in sys.path:
21
15
  sys.path.insert(0, parent_directory)
22
16
 
23
- from _claude_permissions_common import ( # noqa: E402
17
+ from _bugteam_permissions_common import ( # noqa: E402
24
18
  build_agent_config_deny_rules,
25
19
  build_permission_rules,
26
20
  exit_with_error,
@@ -31,7 +25,7 @@ from _claude_permissions_common import ( # noqa: E402
31
25
  remove_matching_entries_from_list,
32
26
  save_settings,
33
27
  )
34
- from config.claude_permissions_common_constants import ( # noqa: E402
28
+ from bugteam_scripts_constants.claude_permissions_common_constants import ( # noqa: E402
35
29
  ALL_AGENT_CONFIG_DENY_TOOLS,
36
30
  ALL_AGENT_CONFIG_PATH_PATTERNS,
37
31
  ALL_PERMISSION_ALLOW_TOOLS,
@@ -1,10 +1,10 @@
1
- """TDD-pair tests for the underscore-prefixed _claude_permissions_common module.
1
+ """TDD-pair tests for the underscore-prefixed _bugteam_permissions_common module.
2
2
 
3
3
  The TDD enforcer matches a production filename ``X.py`` to ``test_X.py``;
4
- ``_claude_permissions_common.py`` carries a leading underscore that the
4
+ ``_bugteam_permissions_common.py`` carries a leading underscore that the
5
5
  enforcer treats as part of the name. This file's tests are the canonical
6
6
  match. The broader behavioral suite continues to live alongside, in
7
- ``test_claude_permissions_common.py``.
7
+ ``test_bugteam_permissions_common.py``.
8
8
  """
9
9
  from __future__ import annotations
10
10
 
@@ -18,7 +18,7 @@ _script_directory = str(Path(__file__).resolve().parent)
18
18
  if _script_directory not in sys.path:
19
19
  sys.path.insert(0, _script_directory)
20
20
 
21
- import _claude_permissions_common as common_module
21
+ import _bugteam_permissions_common as common_module
22
22
  import grant_project_claude_permissions as grant_module
23
23
  import revoke_project_claude_permissions as revoke_module
24
24
 
@@ -21,10 +21,10 @@ _script_directory = str(Path(__file__).resolve().parent)
21
21
  if _script_directory not in sys.path:
22
22
  sys.path.insert(0, _script_directory)
23
23
 
24
- import _claude_permissions_common as common_module
24
+ import _bugteam_permissions_common as common_module
25
25
  import grant_project_claude_permissions as grant_module
26
26
  import revoke_project_claude_permissions as revoke_module
27
- from config.claude_permissions_common_constants import (
27
+ from bugteam_scripts_constants.claude_permissions_common_constants import (
28
28
  ALL_AGENT_CONFIG_DENY_TOOLS,
29
29
  ALL_AGENT_CONFIG_PATH_PATTERNS,
30
30
  ALL_PERMISSION_ALLOW_TOOLS,
@@ -356,29 +356,3 @@ def test_read_global_core_hooks_path_returns_empty_when_key_unset() -> None:
356
356
  with patch.object(subprocess, "run", fake_run):
357
357
  result = bugteam_fix_hookspath.read_global_core_hooks_path(None)
358
358
  assert result == ""
359
-
360
-
361
- def test_module_import_evicts_cached_config_submodules() -> None:
362
- """Importing bugteam_fix_hookspath must evict cached `config.*` submodules.
363
-
364
- Regression for loop1-1: without a defensive cache pop above sys.path.insert,
365
- a previously-cached `config` package shadows scripts/config/ and the
366
- from-import raises ModuleNotFoundError.
367
- """
368
- fake_submodule_name = "config.bugteam_fix_hookspath_constants"
369
- fake_parent_name = "config"
370
- sentinel_module_a = ModuleType(fake_parent_name)
371
- sentinel_module_b = ModuleType(fake_submodule_name)
372
- sys.modules[fake_parent_name] = sentinel_module_a
373
- sys.modules[fake_submodule_name] = sentinel_module_b
374
- try:
375
- _load_fix_module()
376
- finally:
377
- sys.modules.pop(fake_parent_name, None)
378
- sys.modules.pop(fake_submodule_name, None)
379
- assert sys.modules.get(fake_parent_name) is not sentinel_module_a, (
380
- "parent `config` cache entry must be evicted on module import"
381
- )
382
- assert sys.modules.get(fake_submodule_name) is not sentinel_module_b, (
383
- "cached `config.<submodule>` entries must be evicted on module import"
384
- )
@@ -1,7 +1,5 @@
1
- import importlib
2
1
  import sys
3
2
  from pathlib import Path
4
- from types import ModuleType
5
3
  from unittest.mock import patch
6
4
 
7
5
  import pytest
@@ -10,14 +8,14 @@ _script_directory = str(Path(__file__).resolve().parent)
10
8
  if _script_directory not in sys.path:
11
9
  sys.path.insert(0, _script_directory)
12
10
 
13
- import _claude_permissions_common as common_module
14
- from _claude_permissions_common import (
11
+ import _bugteam_permissions_common as common_module
12
+ from _bugteam_permissions_common import (
15
13
  build_permission_rule,
16
14
  get_current_project_path,
17
15
  path_contains_glob_metacharacters,
18
16
  save_settings,
19
17
  )
20
- from config.claude_permissions_common_constants import DEFAULT_SETTINGS_FILE_MODE
18
+ from bugteam_scripts_constants.claude_permissions_common_constants import DEFAULT_SETTINGS_FILE_MODE
21
19
  import grant_project_claude_permissions as grant_module
22
20
  import revoke_project_claude_permissions as revoke_module
23
21
 
@@ -140,64 +138,3 @@ def test_is_valid_project_root_exported_from_consumer_modules(
140
138
  assert revoke_module.is_valid_project_root(bare_directory) is False
141
139
 
142
140
 
143
- def _reload_with_stale_config_cache(module_name: str) -> ModuleType:
144
- fake_submodule_name = "config.claude_permissions_common_constants"
145
- fake_parent_name = "config"
146
- sentinel_module_a = ModuleType(fake_parent_name)
147
- sentinel_module_b = ModuleType(fake_submodule_name)
148
- sys.modules[fake_parent_name] = sentinel_module_a
149
- sys.modules[fake_submodule_name] = sentinel_module_b
150
- try:
151
- target_module = sys.modules.get(module_name)
152
- if target_module is None:
153
- target_module = importlib.import_module(module_name)
154
- else:
155
- target_module = importlib.reload(target_module)
156
- finally:
157
- sys.modules.pop(fake_parent_name, None)
158
- sys.modules.pop(fake_submodule_name, None)
159
- return target_module
160
-
161
-
162
- def test_grant_module_import_evicts_cached_config_submodules(
163
- tmp_path: Path,
164
- ) -> None:
165
- """grant_project_claude_permissions must evict cached `config.*` on import.
166
-
167
- Regression for loop1-2: without a defensive cache pop above sys.path.insert,
168
- a cached `config` package shadows scripts/config/ and the from-import raises.
169
- Calls the rebound `is_valid_project_root` to confirm the real implementation
170
- survived the cache eviction (a stale shadow would either raise on import or
171
- bind a placeholder that returns the wrong value).
172
- """
173
- reloaded_module = _reload_with_stale_config_cache(
174
- "grant_project_claude_permissions"
175
- )
176
- real_project_root = tmp_path / "project_root"
177
- (real_project_root / ".claude").mkdir(parents=True)
178
- bare_directory = tmp_path / "no_claude_marker"
179
- bare_directory.mkdir()
180
- assert reloaded_module.is_valid_project_root(real_project_root) is True
181
- assert reloaded_module.is_valid_project_root(bare_directory) is False
182
-
183
-
184
- def test_revoke_module_import_evicts_cached_config_submodules(
185
- tmp_path: Path,
186
- ) -> None:
187
- """revoke_project_claude_permissions must evict cached `config.*` on import.
188
-
189
- Regression for loop1-3: without a defensive cache pop above sys.path.insert,
190
- a cached `config` package shadows scripts/config/ and the from-import raises.
191
- Calls the rebound `is_valid_project_root` to confirm the real implementation
192
- survived the cache eviction (a stale shadow would either raise on import or
193
- bind a placeholder that returns the wrong value).
194
- """
195
- reloaded_module = _reload_with_stale_config_cache(
196
- "revoke_project_claude_permissions"
197
- )
198
- real_project_root = tmp_path / "project_root"
199
- (real_project_root / ".claude").mkdir(parents=True)
200
- bare_directory = tmp_path / "no_claude_marker"
201
- bare_directory.mkdir()
202
- assert reloaded_module.is_valid_project_root(real_project_root) is True
203
- assert reloaded_module.is_valid_project_root(bare_directory) is False
@@ -210,38 +210,13 @@ def test_should_exit_nonzero_when_subprocess_run_raises_os_error(
210
210
  )
211
211
 
212
212
 
213
- def test_module_import_evicts_cached_config_submodules() -> None:
214
- """Importing bugteam_preflight must evict cached `config.*` submodules.
215
-
216
- Regression for loop1-4: a single `sys.modules.pop("config", None)` only
217
- removes the parent key, leaving stale `config.<submodule>` entries that
218
- satisfy the next from-import with the wrong bindings.
219
- """
220
- fake_submodule_name = "config.bugteam_preflight_constants"
221
- fake_parent_name = "config"
222
- sentinel_module_a = ModuleType(fake_parent_name)
223
- sentinel_module_b = ModuleType(fake_submodule_name)
224
- sys.modules[fake_parent_name] = sentinel_module_a
225
- sys.modules[fake_submodule_name] = sentinel_module_b
226
- try:
227
- _load_preflight_module()
228
- finally:
229
- sys.modules.pop(fake_parent_name, None)
230
- sys.modules.pop(fake_submodule_name, None)
231
- assert sys.modules.get(fake_parent_name) is not sentinel_module_a, (
232
- "parent `config` cache entry must be evicted on module import"
233
- )
234
- assert sys.modules.get(fake_submodule_name) is not sentinel_module_b, (
235
- "cached `config.<submodule>` entries must be evicted on module import"
236
- )
237
-
238
-
239
213
  def test_has_pytest_configuration_finds_pytest_ini(tmp_path: Path) -> None:
240
214
  """has_pytest_configuration must detect pytest.ini at the repo root.
241
215
 
242
216
  Regression for loop1-17/loop1-18: the literals "pytest.ini",
243
217
  "pyproject.toml", and "[tool.pytest" were inlined in production function
244
- bodies; centralizing them in config and importing here pins the contract.
218
+ bodies; centralizing them in bugteam_scripts_constants and importing here
219
+ pins the contract.
245
220
  """
246
221
  repository_root = tmp_path / "repo"
247
222
  repository_root.mkdir()
@@ -16,7 +16,7 @@ import stat
16
16
  import sys
17
17
  from collections.abc import Callable
18
18
 
19
- from config.windows_safe_rmtree_constants import (
19
+ from bugteam_scripts_constants.windows_safe_rmtree_constants import (
20
20
  EXIT_CODE_REMOVE_TREE_FAILURE,
21
21
  EXIT_CODE_USAGE_ERROR,
22
22
  EXPECTED_ARGUMENT_COUNT,
@@ -94,6 +94,6 @@ Read the matching example for the artifact you're designing. Crib palette, typog
94
94
 
95
95
  - `SKILL.md` — this file.
96
96
  - `skills/doc-gist/scripts/gist_upload.py` — transport: HTML in, gist + preview URLs out.
97
- - `skills/doc-gist/scripts/config/gist_upload_constants.py` — the URL prefixes and template strings.
97
+ - `skills/doc-gist/scripts/doc_gist_scripts_constants/gist_upload_constants.py` — the URL prefixes and template strings.
98
98
  - `references/examples/` — Thariq's 20 html-effectiveness prototypes.
99
99
  - (PostToolUse hook lives in `packages/claude-dev-env/hooks/workflow/doc_gist_auto_publish.py` — wired into the plugin's `hooks.json`.)
@@ -30,7 +30,7 @@ _script_directory = str(Path(__file__).resolve().parent)
30
30
  if _script_directory not in sys.path:
31
31
  sys.path.insert(0, _script_directory)
32
32
 
33
- from config.gist_upload_constants import ( # noqa: E402
33
+ from doc_gist_scripts_constants.gist_upload_constants import ( # noqa: E402
34
34
  GIST_DEFAULT_FILENAME,
35
35
  GIST_HOST_PREFIX,
36
36
  MINIMUM_GIST_URL_PARTS,
@@ -62,5 +62,5 @@ Append entries as decisions are made — do not batch them until the end.
62
62
  | File | Purpose |
63
63
  |---|---|
64
64
  | `SKILL.md` | This hub |
65
- | `scripts/append_note.py` | CLI to append one entry to a section |
66
- | `scripts/config/notes_constants.py` | Section slugs → headings and default filename |
65
+ | `packages/claude-dev-env/skills/implement/scripts/append_note.py` | CLI to append one entry to a section |
66
+ | `packages/claude-dev-env/skills/implement/scripts/implement_scripts_constants/notes_constants.py` | Section slugs → headings and default filename |
@@ -16,7 +16,7 @@ import html
16
16
  import sys
17
17
  from pathlib import Path
18
18
 
19
- from config.notes_constants import DEFAULT_NOTES_FILENAME, HEADING_BY_SLUG
19
+ from implement_scripts_constants.notes_constants import DEFAULT_NOTES_FILENAME, HEADING_BY_SLUG
20
20
 
21
21
 
22
22
  def _build_skeleton() -> str:
@@ -2,7 +2,7 @@
2
2
 
3
3
  All runtime and API constants live here. Script-specific constants
4
4
  (CLI args, markdown patterns, reflow settings) stay in
5
- ``packages/claude-dev-env/skills/pr-converge/scripts/config/pr_converge_constants.py``,
5
+ ``packages/claude-dev-env/skills/pr-converge/scripts/pr_converge_scripts_constants/pr_converge_constants.py``,
6
6
  which imports from here.
7
7
  """
8
8