claude-dev-env 1.58.0 → 1.59.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 (52) hide show
  1. package/CLAUDE.md +2 -2
  2. package/_shared/pr-loop/scripts/code_rules_gate.py +36 -3
  3. package/_shared/pr-loop/scripts/pr_loop_shared_constants/code_rules_gate_constants.py +6 -0
  4. package/_shared/pr-loop/scripts/pr_loop_shared_constants/reviews_disabled_constants.py +1 -0
  5. package/_shared/pr-loop/scripts/reviews_disabled.py +12 -0
  6. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +265 -0
  7. package/_shared/pr-loop/scripts/tests/test_reviews_disabled.py +29 -0
  8. package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +1 -1
  9. package/bin/install.mjs +100 -27
  10. package/bin/install.test.mjs +133 -1
  11. package/docs/CODE_RULES.md +3 -3
  12. package/hooks/blocking/code_rules_annotations_length.py +153 -0
  13. package/hooks/blocking/code_rules_dead_dataclass_field.py +319 -0
  14. package/hooks/blocking/code_rules_duplicate_body.py +287 -0
  15. package/hooks/blocking/code_rules_enforcer.py +175 -21
  16. package/hooks/blocking/code_rules_magic_values.py +98 -0
  17. package/hooks/blocking/code_rules_shared.py +41 -0
  18. package/hooks/blocking/destructive_command_blocker.py +1027 -12
  19. package/hooks/blocking/hook_prose_detector_consistency.py +150 -0
  20. package/hooks/blocking/subprocess_budget_completeness.py +380 -0
  21. package/hooks/blocking/test_code_rules_enforcer_annotations.py +225 -0
  22. package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +1 -0
  23. package/hooks/blocking/test_code_rules_enforcer_dead_dataclass_field.py +467 -0
  24. package/hooks/blocking/test_code_rules_enforcer_duplicate_body.py +330 -0
  25. package/hooks/blocking/test_code_rules_enforcer_duplicate_body_hook_routing.py +179 -0
  26. package/hooks/blocking/test_code_rules_enforcer_magic_slice_bounds.py +133 -0
  27. package/hooks/blocking/test_destructive_command_blocker.py +622 -3
  28. package/hooks/blocking/test_hook_prose_detector_consistency.py +265 -0
  29. package/hooks/blocking/test_subprocess_budget_completeness.py +588 -0
  30. package/hooks/blocking/test_workflow_substitution_slot_blocker.py +242 -0
  31. package/hooks/blocking/workflow_substitution_slot_blocker.py +159 -0
  32. package/hooks/hooks.json +15 -0
  33. package/hooks/hooks_constants/code_rules_enforcer_constants.py +16 -0
  34. package/hooks/hooks_constants/dead_dataclass_field_constants.py +25 -0
  35. package/hooks/hooks_constants/destructive_command_segment_constants.py +178 -0
  36. package/hooks/hooks_constants/duplicate_function_body_constants.py +17 -0
  37. package/hooks/hooks_constants/hook_prose_detector_consistency_constants.py +30 -0
  38. package/hooks/hooks_constants/subprocess_budget_completeness_constants.py +5 -0
  39. package/hooks/hooks_constants/workflow_substitution_slot_blocker_constants.py +22 -0
  40. package/package.json +1 -1
  41. package/rules/docstring-prose-matches-implementation.md +43 -0
  42. package/rules/hook-prose-matches-detector.md +26 -0
  43. package/rules/no-inline-destructive-literals.md +11 -0
  44. package/rules/workflow-substitution-slots.md +7 -0
  45. package/skills/autoconverge/SKILL.md +13 -2
  46. package/skills/autoconverge/reference/convergence.md +7 -3
  47. package/skills/autoconverge/reference/stop-conditions.md +7 -2
  48. package/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +265 -0
  49. package/skills/autoconverge/workflow/converge.mjs +106 -36
  50. package/skills/pr-converge/scripts/check_convergence.py +195 -64
  51. package/skills/pr-converge/scripts/test_check_convergence.py +173 -2
  52. package/skills/update/SKILL.md +37 -5
@@ -0,0 +1,330 @@
1
+ """Tests for cross-file duplicate top-level function body detection.
2
+
3
+ PR #567 added the 5th and 6th copies of a byte-identical ``strip_code_and_quotes``
4
+ helper across sibling Stop-hook modules. This check blocks that violation class at
5
+ Write time: a top-level function whose body matches a top-level function in a
6
+ sibling ``.py`` module in the same directory is flagged so the author extracts one
7
+ shared helper instead of copying it.
8
+
9
+ The tests write real sibling files into a neutrally named temporary directory and
10
+ run the check against them, so they exercise the on-disk directory scan rather
11
+ than a stubbed view of the filesystem. The directory is named like a production
12
+ package directory (no ``test_`` segment), because the check treats any path
13
+ containing a test marker as exempt — the same way it would skip a real test file.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import importlib.util
19
+ import pathlib
20
+ import shutil
21
+ import sys
22
+ import tempfile
23
+ from collections.abc import Iterator
24
+
25
+ import pytest
26
+
27
+ _HOOK_DIRECTORY = pathlib.Path(__file__).parent
28
+ if str(_HOOK_DIRECTORY) not in sys.path:
29
+ sys.path.insert(0, str(_HOOK_DIRECTORY))
30
+
31
+ _hook_spec = importlib.util.spec_from_file_location(
32
+ "code_rules_enforcer",
33
+ _HOOK_DIRECTORY / "code_rules_enforcer.py",
34
+ )
35
+ assert _hook_spec is not None
36
+ assert _hook_spec.loader is not None
37
+ _hook_module = importlib.util.module_from_spec(_hook_spec)
38
+ _hook_spec.loader.exec_module(_hook_module)
39
+ check_duplicate_function_body_across_files = _hook_module.check_duplicate_function_body_across_files
40
+
41
+
42
+ SHARED_HELPER_SOURCE = (
43
+ "import re\n"
44
+ "\n"
45
+ "def strip_code_and_quotes(text: str) -> str:\n"
46
+ " without_fences = re.sub(r'```.*?```', '', text, flags=re.DOTALL)\n"
47
+ " without_inline = re.sub(r'`[^`]*`', '', without_fences)\n"
48
+ " without_quotes = re.sub(r'(?m)^>.*$', '', without_inline)\n"
49
+ " return without_quotes.strip()\n"
50
+ )
51
+
52
+
53
+ @pytest.fixture
54
+ def module_dir() -> Iterator[pathlib.Path]:
55
+ base_directory = pathlib.Path(tempfile.mkdtemp())
56
+ package_directory = base_directory / "blocking"
57
+ package_directory.mkdir()
58
+ try:
59
+ yield package_directory
60
+ finally:
61
+ shutil.rmtree(base_directory, ignore_errors=False)
62
+
63
+
64
+ def _write(directory: pathlib.Path, name: str, source: str) -> pathlib.Path:
65
+ target = directory / name
66
+ target.write_text(source, encoding="utf-8")
67
+ return target
68
+
69
+
70
+ def test_should_flag_function_copied_from_sibling(module_dir: pathlib.Path) -> None:
71
+ _write(module_dir, "existing_blocker.py", SHARED_HELPER_SOURCE)
72
+ new_file = module_dir / "new_blocker.py"
73
+ issues = check_duplicate_function_body_across_files(SHARED_HELPER_SOURCE, str(new_file))
74
+ assert any("strip_code_and_quotes" in each_issue for each_issue in issues), (
75
+ f"Expected the copied helper to be flagged, got: {issues}"
76
+ )
77
+ assert any("existing_blocker.py" in each_issue for each_issue in issues), (
78
+ f"Expected the sibling source location named, got: {issues}"
79
+ )
80
+
81
+
82
+ def test_should_not_flag_when_no_sibling_matches(module_dir: pathlib.Path) -> None:
83
+ _write(
84
+ module_dir,
85
+ "unrelated.py",
86
+ "def add(left: int, right: int) -> int:\n"
87
+ " total = left + right\n"
88
+ " doubled = total * 2\n"
89
+ " return doubled\n",
90
+ )
91
+ new_file = module_dir / "new_blocker.py"
92
+ issues = check_duplicate_function_body_across_files(SHARED_HELPER_SOURCE, str(new_file))
93
+ assert issues == [], f"No matching sibling body must not flag, got: {issues}"
94
+
95
+
96
+ def test_should_not_flag_trivial_short_body(module_dir: pathlib.Path) -> None:
97
+ trivial_source = "def noop() -> None:\n return None\n"
98
+ _write(module_dir, "existing.py", trivial_source)
99
+ new_file = module_dir / "new.py"
100
+ issues = check_duplicate_function_body_across_files(trivial_source, str(new_file))
101
+ assert issues == [], (
102
+ f"A body under the minimum statement count is too common to flag, got: {issues}"
103
+ )
104
+
105
+
106
+ def test_should_ignore_docstring_only_difference(module_dir: pathlib.Path) -> None:
107
+ with_docstring = (
108
+ "def compute(left: int, right: int) -> int:\n"
109
+ ' """Add then scale."""\n'
110
+ " total = left + right\n"
111
+ " scaled = total * 3\n"
112
+ " return scaled\n"
113
+ )
114
+ without_docstring = (
115
+ "def compute(left: int, right: int) -> int:\n"
116
+ " total = left + right\n"
117
+ " scaled = total * 3\n"
118
+ " return scaled\n"
119
+ )
120
+ _write(module_dir, "existing.py", with_docstring)
121
+ new_file = module_dir / "new.py"
122
+ issues = check_duplicate_function_body_across_files(without_docstring, str(new_file))
123
+ assert any("compute" in each_issue for each_issue in issues), (
124
+ f"A docstring-only difference must not hide the duplicate, got: {issues}"
125
+ )
126
+
127
+
128
+ def test_should_skip_test_file_being_written(module_dir: pathlib.Path) -> None:
129
+ _write(module_dir, "existing.py", SHARED_HELPER_SOURCE)
130
+ test_file = module_dir / "test_new.py"
131
+ issues = check_duplicate_function_body_across_files(SHARED_HELPER_SOURCE, str(test_file))
132
+ assert issues == [], f"Test files are exempt on the writing side, got: {issues}"
133
+
134
+
135
+ def test_should_skip_test_file_siblings(module_dir: pathlib.Path) -> None:
136
+ _write(module_dir, "test_existing.py", SHARED_HELPER_SOURCE)
137
+ new_file = module_dir / "new_blocker.py"
138
+ issues = check_duplicate_function_body_across_files(SHARED_HELPER_SOURCE, str(new_file))
139
+ assert issues == [], (
140
+ f"A matching body in a sibling test file must not flag production code, got: {issues}"
141
+ )
142
+
143
+
144
+ def test_should_skip_dunder_init_being_written(module_dir: pathlib.Path) -> None:
145
+ _write(module_dir, "existing.py", SHARED_HELPER_SOURCE)
146
+ init_file = module_dir / "__init__.py"
147
+ issues = check_duplicate_function_body_across_files(SHARED_HELPER_SOURCE, str(init_file))
148
+ assert issues == [], f"__init__.py re-export surfaces are exempt, got: {issues}"
149
+
150
+
151
+ def test_should_not_compare_against_self(module_dir: pathlib.Path) -> None:
152
+ existing = _write(module_dir, "blocker.py", SHARED_HELPER_SOURCE)
153
+ issues = check_duplicate_function_body_across_files(SHARED_HELPER_SOURCE, str(existing))
154
+ assert issues == [], (
155
+ f"A file must not be flagged as a duplicate of its own on-disk copy, got: {issues}"
156
+ )
157
+
158
+
159
+ def test_should_return_empty_on_syntax_error(module_dir: pathlib.Path) -> None:
160
+ _write(module_dir, "existing.py", SHARED_HELPER_SOURCE)
161
+ new_file = module_dir / "broken.py"
162
+ issues = check_duplicate_function_body_across_files("def broken(\n", str(new_file))
163
+ assert issues == [], f"Unparseable content must return empty, got: {issues}"
164
+
165
+
166
+ def test_should_skip_unparseable_sibling(module_dir: pathlib.Path) -> None:
167
+ _write(module_dir, "broken_sibling.py", "def broken(\n")
168
+ _write(module_dir, "good_sibling.py", SHARED_HELPER_SOURCE)
169
+ new_file = module_dir / "new.py"
170
+ issues = check_duplicate_function_body_across_files(SHARED_HELPER_SOURCE, str(new_file))
171
+ assert any("good_sibling.py" in each_issue for each_issue in issues), (
172
+ f"A broken sibling must be skipped without hiding a real match, got: {issues}"
173
+ )
174
+
175
+
176
+ def test_should_not_flag_method_inside_class(module_dir: pathlib.Path) -> None:
177
+ class_source = (
178
+ "class Worker:\n"
179
+ " def run(self, left: int, right: int) -> int:\n"
180
+ " total = left + right\n"
181
+ " scaled = total * 4\n"
182
+ " return scaled\n"
183
+ )
184
+ _write(module_dir, "existing.py", class_source)
185
+ new_file = module_dir / "new.py"
186
+ issues = check_duplicate_function_body_across_files(class_source, str(new_file))
187
+ assert issues == [], f"Only module-scope functions are compared, not methods, got: {issues}"
188
+
189
+
190
+ _UNRELATED_LEADING_FUNCTION = (
191
+ "def unrelated_helper(left: int, right: int) -> int:\n"
192
+ " summed = left + right\n"
193
+ " tripled = summed * 3\n"
194
+ " return tripled\n"
195
+ )
196
+
197
+
198
+ def test_should_not_flag_when_edit_leaves_duplicate_outside_changed_lines(
199
+ module_dir: pathlib.Path,
200
+ ) -> None:
201
+ _write(module_dir, "existing.py", SHARED_HELPER_SOURCE)
202
+ new_file = module_dir / "new_blocker.py"
203
+ post_edit_content = _UNRELATED_LEADING_FUNCTION + "\n\n" + SHARED_HELPER_SOURCE
204
+ changed_lines_outside_duplicate = {1, 2, 3, 4}
205
+ issues = check_duplicate_function_body_across_files(
206
+ post_edit_content,
207
+ str(new_file),
208
+ all_changed_lines=changed_lines_outside_duplicate,
209
+ )
210
+ assert issues == [], (
211
+ "An Edit that never touches the duplicated function must not block, "
212
+ f"got: {issues}"
213
+ )
214
+
215
+
216
+ def test_should_flag_when_edit_changed_lines_intersect_duplicate(
217
+ module_dir: pathlib.Path,
218
+ ) -> None:
219
+ _write(module_dir, "existing.py", SHARED_HELPER_SOURCE)
220
+ new_file = module_dir / "new_blocker.py"
221
+ post_edit_content = _UNRELATED_LEADING_FUNCTION + "\n\n" + SHARED_HELPER_SOURCE
222
+ duplicate_definition_line = post_edit_content.splitlines().index(
223
+ "def strip_code_and_quotes(text: str) -> str:"
224
+ ) + 1
225
+ changed_lines_inside_duplicate = {duplicate_definition_line + 1}
226
+ issues = check_duplicate_function_body_across_files(
227
+ post_edit_content,
228
+ str(new_file),
229
+ all_changed_lines=changed_lines_inside_duplicate,
230
+ )
231
+ assert any("strip_code_and_quotes" in each_issue for each_issue in issues), (
232
+ "An Edit whose changed lines touch the copied helper must still flag, "
233
+ f"got: {issues}"
234
+ )
235
+
236
+
237
+ def test_should_flag_whole_file_write_when_changed_lines_is_none(
238
+ module_dir: pathlib.Path,
239
+ ) -> None:
240
+ _write(module_dir, "existing.py", SHARED_HELPER_SOURCE)
241
+ new_file = module_dir / "new_blocker.py"
242
+ issues = check_duplicate_function_body_across_files(
243
+ SHARED_HELPER_SOURCE,
244
+ str(new_file),
245
+ all_changed_lines=None,
246
+ )
247
+ assert any("strip_code_and_quotes" in each_issue for each_issue in issues), (
248
+ "A whole-file Write treats every line as in scope and must flag, "
249
+ f"got: {issues}"
250
+ )
251
+
252
+
253
+ def test_should_scan_explicit_sibling_directory_for_relative_path(
254
+ module_dir: pathlib.Path,
255
+ ) -> None:
256
+ _write(module_dir, "existing_blocker.py", SHARED_HELPER_SOURCE)
257
+ issues = check_duplicate_function_body_across_files(
258
+ SHARED_HELPER_SOURCE,
259
+ "package/new_blocker.py",
260
+ sibling_directory=module_dir,
261
+ )
262
+ assert any("strip_code_and_quotes" in each_issue for each_issue in issues), (
263
+ "When given an explicit sibling directory, the check must scan it for a "
264
+ f"relative file_path rather than the path's CWD-relative parent, got: {issues}"
265
+ )
266
+ assert any("existing_blocker.py" in each_issue for each_issue in issues), (
267
+ f"Expected the sibling source location named, got: {issues}"
268
+ )
269
+
270
+
271
+ def test_should_ignore_cwd_when_explicit_sibling_directory_given(
272
+ module_dir: pathlib.Path,
273
+ monkeypatch: pytest.MonkeyPatch,
274
+ ) -> None:
275
+ _write(module_dir, "existing_blocker.py", SHARED_HELPER_SOURCE)
276
+ monkeypatch.chdir(module_dir.parent)
277
+ issues = check_duplicate_function_body_across_files(
278
+ SHARED_HELPER_SOURCE,
279
+ "package/new_blocker.py",
280
+ sibling_directory=module_dir,
281
+ )
282
+ assert any("strip_code_and_quotes" in each_issue for each_issue in issues), (
283
+ "An explicit sibling directory must anchor the scan independent of the "
284
+ f"process working directory, got: {issues}"
285
+ )
286
+
287
+
288
+ def test_should_return_every_violation_when_scope_deferred_to_caller(
289
+ module_dir: pathlib.Path,
290
+ ) -> None:
291
+ _write(module_dir, "existing.py", SHARED_HELPER_SOURCE)
292
+ new_file = module_dir / "new_blocker.py"
293
+ post_edit_content = _UNRELATED_LEADING_FUNCTION + "\n\n" + SHARED_HELPER_SOURCE
294
+ changed_lines_outside_duplicate = {1, 2, 3, 4}
295
+ issues = check_duplicate_function_body_across_files(
296
+ post_edit_content,
297
+ str(new_file),
298
+ all_changed_lines=changed_lines_outside_duplicate,
299
+ defer_scope_to_caller=True,
300
+ )
301
+ assert any("strip_code_and_quotes" in each_issue for each_issue in issues), (
302
+ "The commit/push gate scopes by added line, so the check must return "
303
+ f"every violation when scope is deferred, got: {issues}"
304
+ )
305
+
306
+
307
+ def test_should_carry_a_parseable_span_for_the_commit_gate_scoper(
308
+ module_dir: pathlib.Path,
309
+ ) -> None:
310
+ _write(module_dir, "existing.py", SHARED_HELPER_SOURCE)
311
+ new_file = module_dir / "new_blocker.py"
312
+ post_edit_content = _UNRELATED_LEADING_FUNCTION + "\n\n" + SHARED_HELPER_SOURCE
313
+ duplicate_definition_line = post_edit_content.splitlines().index(
314
+ "def strip_code_and_quotes(text: str) -> str:"
315
+ ) + 1
316
+ issues = check_duplicate_function_body_across_files(
317
+ post_edit_content,
318
+ str(new_file),
319
+ all_changed_lines=None,
320
+ defer_scope_to_caller=True,
321
+ )
322
+ matching_issues = [
323
+ each_issue for each_issue in issues if "strip_code_and_quotes" in each_issue
324
+ ]
325
+ assert matching_issues, f"expected a duplicate-body issue, got: {issues}"
326
+ expected_fragment = f"(duplicate body span at line {duplicate_definition_line}, spanning 5 lines)"
327
+ assert expected_fragment in matching_issues[0], (
328
+ "The commit gate's scope splitter parses the copied function's span from "
329
+ f"the message, so the message must carry it, got: {matching_issues[0]}"
330
+ )
@@ -0,0 +1,179 @@
1
+ """Entry-point tests proving the duplicate-body check guards hook-infrastructure files.
2
+
3
+ The cross-file duplicate-body check exists to catch a helper copied across sibling
4
+ modules in the ``blocking/`` hook directory itself — the exact directory the rest of
5
+ the code-rules suite exempts. These tests drive the real entry points (the ``main()``
6
+ stdin path and the pre-check CLI) with a hook-infrastructure target so the deny fires
7
+ on the same path a live Write would take, rather than calling the check function
8
+ directly.
9
+
10
+ Each test builds a temporary tree whose tail mirrors a production hook directory
11
+ (``packages/claude-dev-env/hooks/blocking``) so ``is_hook_infrastructure`` matches the
12
+ target path the same way it would for the real directory.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import io
18
+ import json
19
+ import pathlib
20
+ import shutil
21
+ import subprocess
22
+ import sys
23
+ import tempfile
24
+ from collections.abc import Iterator
25
+ from types import SimpleNamespace
26
+
27
+ import pytest
28
+
29
+ _HOOK_DIRECTORY = pathlib.Path(__file__).resolve().parent
30
+ _HOOKS_PARENT = _HOOK_DIRECTORY.parent
31
+ if str(_HOOK_DIRECTORY) not in sys.path:
32
+ sys.path.insert(0, str(_HOOK_DIRECTORY))
33
+ if str(_HOOKS_PARENT) not in sys.path:
34
+ sys.path.insert(0, str(_HOOKS_PARENT))
35
+
36
+ from code_rules_enforcer import main # noqa: E402
37
+
38
+ code_rules_enforcer = SimpleNamespace(main=main, sys=sys)
39
+
40
+ _ENFORCER_SCRIPT_PATH = _HOOK_DIRECTORY / "code_rules_enforcer.py"
41
+
42
+ SHARED_HELPER_SOURCE = (
43
+ "import re\n"
44
+ "\n"
45
+ "def strip_code_and_quotes(text: str) -> str:\n"
46
+ " without_fences = re.sub(r'```.*?```', '', text, flags=re.DOTALL)\n"
47
+ " without_inline = re.sub(r'`[^`]*`', '', without_fences)\n"
48
+ " without_quotes = re.sub(r'(?m)^>.*$', '', without_inline)\n"
49
+ " return without_quotes.strip()\n"
50
+ )
51
+
52
+ _HOOK_INFRASTRUCTURE_TAIL = pathlib.Path("packages") / "claude-dev-env" / "hooks" / "blocking"
53
+
54
+
55
+ @pytest.fixture
56
+ def hook_blocking_dir() -> Iterator[pathlib.Path]:
57
+ base_directory = pathlib.Path(tempfile.mkdtemp())
58
+ blocking_directory = base_directory / _HOOK_INFRASTRUCTURE_TAIL
59
+ blocking_directory.mkdir(parents=True)
60
+ try:
61
+ yield blocking_directory
62
+ finally:
63
+ shutil.rmtree(base_directory, ignore_errors=False)
64
+
65
+
66
+ def _run_main_with_write_payload(
67
+ file_path: str,
68
+ content: str,
69
+ monkeypatch: pytest.MonkeyPatch,
70
+ capsys: pytest.CaptureFixture[str],
71
+ ) -> str:
72
+ """Drive ``main()`` through its stdin entry point for a Write and return stdout.
73
+
74
+ Args:
75
+ file_path: The on-disk path the Write targets.
76
+ content: The whole-file body the Write would create.
77
+ monkeypatch: The fixture used to redirect ``sys.stdin``.
78
+ capsys: The fixture used to capture the deny payload on stdout.
79
+
80
+ Returns:
81
+ The captured stdout, which holds the deny payload when violations fire.
82
+ """
83
+ write_payload = json.dumps(
84
+ {
85
+ "tool_name": "Write",
86
+ "tool_input": {"file_path": file_path, "content": content},
87
+ }
88
+ )
89
+ monkeypatch.setattr(code_rules_enforcer.sys, "stdin", io.StringIO(write_payload))
90
+ try:
91
+ code_rules_enforcer.main([])
92
+ except SystemExit:
93
+ pass
94
+ return capsys.readouterr().out
95
+
96
+
97
+ def test_write_of_copied_helper_into_hook_directory_denies(
98
+ hook_blocking_dir: pathlib.Path,
99
+ monkeypatch: pytest.MonkeyPatch,
100
+ capsys: pytest.CaptureFixture[str],
101
+ ) -> None:
102
+ """A Write that copies a sibling helper into a second hook file is denied.
103
+
104
+ The target lives under a hook-infrastructure path the rest of the code-rules
105
+ suite exempts, so this proves the duplicate-body check still guards the exact
106
+ directory its module docstring names as the primary target."""
107
+ (hook_blocking_dir / "existing_blocker.py").write_text(SHARED_HELPER_SOURCE, encoding="utf-8")
108
+ new_file = hook_blocking_dir / "new_blocker.py"
109
+ stdout = _run_main_with_write_payload(str(new_file), SHARED_HELPER_SOURCE, monkeypatch, capsys)
110
+ assert stdout != "", (
111
+ "A copied helper written into a second hook-infrastructure file must "
112
+ "produce a deny payload, got empty stdout"
113
+ )
114
+ deny_payload = json.loads(stdout)
115
+ decision = deny_payload["hookSpecificOutput"]["permissionDecision"]
116
+ reason = deny_payload["hookSpecificOutput"]["permissionDecisionReason"]
117
+ assert decision == "deny", f"expected deny, got: {decision!r}"
118
+ assert "strip_code_and_quotes" in reason, (
119
+ f"the deny reason must name the duplicated helper, got: {reason!r}"
120
+ )
121
+
122
+
123
+ def test_write_of_unique_helper_into_hook_directory_allows(
124
+ hook_blocking_dir: pathlib.Path,
125
+ monkeypatch: pytest.MonkeyPatch,
126
+ capsys: pytest.CaptureFixture[str],
127
+ ) -> None:
128
+ """A Write of a hook file with no sibling duplicate produces no deny payload.
129
+
130
+ Routing hook ``.py`` files to the duplicate-body check must not block a hook
131
+ file that introduces a genuinely new helper; only a copied body denies."""
132
+ (hook_blocking_dir / "existing_blocker.py").write_text(SHARED_HELPER_SOURCE, encoding="utf-8")
133
+ unique_helper_source = (
134
+ "def normalize_indices(left: int, right: int) -> int:\n"
135
+ " combined = left + right\n"
136
+ " widened = combined * 5\n"
137
+ " return widened\n"
138
+ )
139
+ new_file = hook_blocking_dir / "unique_blocker.py"
140
+ stdout = _run_main_with_write_payload(str(new_file), unique_helper_source, monkeypatch, capsys)
141
+ assert stdout == "", f"a unique hook helper must not be denied, got stdout: {stdout!r}"
142
+
143
+
144
+ def test_precheck_of_copied_helper_at_hook_target_exits_nonzero(
145
+ hook_blocking_dir: pathlib.Path,
146
+ tmp_path_factory: pytest.TempPathFactory,
147
+ ) -> None:
148
+ """The pre-check CLI flags a copied helper judged at a hook-infrastructure target.
149
+
150
+ Driving the real ``--check`` argv path proves the gate's pre-check mode also
151
+ routes a hook ``.py`` target through the duplicate-body check rather than
152
+ exiting clean on the blanket hook-infrastructure exemption."""
153
+ (hook_blocking_dir / "existing_blocker.py").write_text(SHARED_HELPER_SOURCE, encoding="utf-8")
154
+ staging_directory = tmp_path_factory.mktemp("staging")
155
+ candidate_file = staging_directory / "candidate.py"
156
+ candidate_file.write_text(SHARED_HELPER_SOURCE, encoding="utf-8")
157
+ target_path = str(hook_blocking_dir / "new_blocker.py")
158
+ completed = subprocess.run(
159
+ [
160
+ sys.executable,
161
+ str(_ENFORCER_SCRIPT_PATH),
162
+ "--check",
163
+ str(candidate_file),
164
+ "--as",
165
+ target_path,
166
+ ],
167
+ input="",
168
+ capture_output=True,
169
+ text=True,
170
+ check=False,
171
+ )
172
+ assert completed.returncode == 1, (
173
+ "a copied helper at a hook target must exit nonzero, got: "
174
+ f"{completed.returncode}, stdout: {completed.stdout!r}, "
175
+ f"stderr: {completed.stderr!r}"
176
+ )
177
+ assert "strip_code_and_quotes" in completed.stdout, (
178
+ f"the pre-check must name the duplicated helper, got: {completed.stdout!r}"
179
+ )
@@ -0,0 +1,133 @@
1
+ """Tests for slice-bound magic values in the magic-value check.
2
+
3
+ CODE_RULES.md states only 0, 1, -1 (plus 0.0, 1.0) are exempt from the
4
+ magic-value check. A magic number used as a slice bound (``sha[:8]``,
5
+ ``timestamp[:10]``) is still a magic value, while a plain subscript index
6
+ (``items[2]``) rides on the bracket exemption. The check distinguishes the
7
+ two by the colon a slice carries between its brackets.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import importlib.util
13
+ from pathlib import Path
14
+ from types import ModuleType
15
+
16
+
17
+ def _load_enforcer_module() -> ModuleType:
18
+ module_path = Path(__file__).parent / "code_rules_enforcer.py"
19
+ spec = importlib.util.spec_from_file_location("code_rules_enforcer", module_path)
20
+ assert spec is not None
21
+ assert spec.loader is not None
22
+ module = importlib.util.module_from_spec(spec)
23
+ spec.loader.exec_module(module)
24
+ return module
25
+
26
+
27
+ code_rules_enforcer = _load_enforcer_module()
28
+
29
+
30
+ PRODUCTION_FILE_PATH = "packages/claude-dev-env/skills/example/workflow/example_render.py"
31
+
32
+
33
+ def test_check_magic_values_should_flag_short_sha_slice_bound() -> None:
34
+ source = (
35
+ "def render_fix(fix_record):\n"
36
+ " short_sha = fix_record.new_sha[:8]\n"
37
+ " label = short_sha\n"
38
+ )
39
+ issues = code_rules_enforcer.check_magic_values(source, PRODUCTION_FILE_PATH)
40
+ assert any(issue.endswith("Magic value 8 - extract to named constant") for issue in issues), (
41
+ f"Expected magic-value issue for slice bound 8, got: {issues}"
42
+ )
43
+
44
+
45
+ def test_check_magic_values_should_flag_iso_date_prefix_slice_bound() -> None:
46
+ source = (
47
+ "def read_date(journal):\n"
48
+ " timestamp = journal.get_timestamp()\n"
49
+ " generated = timestamp[:10]\n"
50
+ " label = generated\n"
51
+ )
52
+ issues = code_rules_enforcer.check_magic_values(source, PRODUCTION_FILE_PATH)
53
+ assert any(issue.endswith("Magic value 10 - extract to named constant") for issue in issues), (
54
+ f"Expected magic-value issue for slice bound 10, got: {issues}"
55
+ )
56
+
57
+
58
+ def test_check_magic_values_should_flag_slice_bound_even_with_inline_guard() -> None:
59
+ source = (
60
+ "def read_date(journal):\n"
61
+ " timestamp = journal.get_timestamp()\n"
62
+ ' generated = timestamp[:10] if len(timestamp) >= 10 else ""\n'
63
+ " label = generated\n"
64
+ )
65
+ issues = code_rules_enforcer.check_magic_values(source, PRODUCTION_FILE_PATH)
66
+ assert any(issue.endswith("Magic value 10 - extract to named constant") for issue in issues), (
67
+ f"Expected magic-value issue for slice bound 10 on a guarded line, got: {issues}"
68
+ )
69
+
70
+
71
+ def test_check_magic_values_should_still_exempt_plain_subscript_index() -> None:
72
+ source = "def pick_entry(all_entries):\n chosen = all_entries[2]\n label = chosen\n"
73
+ issues = code_rules_enforcer.check_magic_values(source, PRODUCTION_FILE_PATH)
74
+ assert issues == [], f"Expected no issues for a plain subscript index, got: {issues}"
75
+
76
+
77
+ def test_check_magic_values_should_allow_slice_bound_of_one() -> None:
78
+ source = "def first_character(text):\n head = text[:1]\n label = head\n"
79
+ issues = code_rules_enforcer.check_magic_values(source, PRODUCTION_FILE_PATH)
80
+ assert issues == [], f"Expected no issues for an allowed slice bound 1, got: {issues}"
81
+
82
+
83
+ def test_check_magic_values_should_flag_slice_bound_not_substring_subscript_on_same_line() -> None:
84
+ source = (
85
+ "def join_pair(key, value):\n"
86
+ " pair = key[2] + value[:20]\n"
87
+ " label = pair\n"
88
+ )
89
+ issues = code_rules_enforcer.check_magic_values(source, PRODUCTION_FILE_PATH)
90
+ assert any(issue.endswith("Magic value 20 - extract to named constant") for issue in issues), (
91
+ f"Expected the slice bound 20 to be flagged, got: {issues}"
92
+ )
93
+ assert not any(issue.endswith("Magic value 2 - extract to named constant") for issue in issues), (
94
+ f"Expected the subscript index 2 to stay exempt, got: {issues}"
95
+ )
96
+
97
+
98
+ def test_check_magic_values_should_flag_first_token_of_two_sided_slice() -> None:
99
+ source = "def middle(chunk):\n window = chunk[8:16]\n label = window\n"
100
+ issues = code_rules_enforcer.check_magic_values(source, PRODUCTION_FILE_PATH)
101
+ assert any(issue.endswith("Magic value 8 - extract to named constant") for issue in issues), (
102
+ f"Expected the first slice bound 8 to be flagged, got: {issues}"
103
+ )
104
+
105
+
106
+ def test_check_magic_values_should_exempt_walrus_subscript_index() -> None:
107
+ source = "def lookup(all_entries):\n chosen = all_entries[(n := 4)]\n label = chosen\n"
108
+ issues = code_rules_enforcer.check_magic_values(source, PRODUCTION_FILE_PATH)
109
+ assert issues == [], f"Expected no issues for a walrus subscript index, got: {issues}"
110
+
111
+
112
+ def test_check_magic_values_should_exempt_lambda_subscript_index() -> None:
113
+ source = "def lookup(sequence):\n chosen = sequence[(lambda: 7)()]\n label = chosen\n"
114
+ issues = code_rules_enforcer.check_magic_values(source, PRODUCTION_FILE_PATH)
115
+ assert issues == [], f"Expected no issues for a lambda subscript index, got: {issues}"
116
+
117
+
118
+ def test_check_magic_values_should_flag_outer_slice_bound_not_inner_subscript() -> None:
119
+ source = "def window(first, second):\n region = first[second[6]:9]\n label = region\n"
120
+ issues = code_rules_enforcer.check_magic_values(source, PRODUCTION_FILE_PATH)
121
+ assert any(issue.endswith("Magic value 9 - extract to named constant") for issue in issues), (
122
+ f"Expected the outer slice bound 9 to be flagged, got: {issues}"
123
+ )
124
+ assert not any(issue.endswith("Magic value 6 - extract to named constant") for issue in issues), (
125
+ f"Expected the inner subscript index 6 to stay exempt, got: {issues}"
126
+ )
127
+
128
+
129
+ def test_check_magic_values_should_pass_on_the_module_own_source() -> None:
130
+ module_path = Path(__file__).parent / "code_rules_magic_values.py"
131
+ source = module_path.read_text(encoding="utf-8")
132
+ issues = code_rules_enforcer.check_magic_values(source, str(module_path))
133
+ assert issues == [], f"Expected the module to pass its own magic-value check, got: {issues}"