claude-dev-env 2.28.0 → 2.28.1

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 (106) hide show
  1. package/.agents/skills-archived/pr-loop-cloud-transport/reference/identity-and-hooks.md +1 -1
  2. package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +16 -29
  3. package/audit-rubrics/prompts/category-o-docstring-vs-impl-drift.md +2 -2
  4. package/docs/CODE_RULES.md +3 -3
  5. package/docs/agent-spawn-protocol.md +1 -1
  6. package/docs/references/prose-style-enforcement.md +5 -9
  7. package/hooks/blocking/AGENTS.md +3 -13
  8. package/hooks/blocking/code_rules_docstrings.py +10 -2138
  9. package/hooks/blocking/code_rules_enforcer.py +0 -121
  10. package/hooks/blocking/code_rules_imports_logging.py +1 -236
  11. package/hooks/blocking/code_rules_shared.py +23 -0
  12. package/hooks/blocking/code_rules_test_layout.py +8 -8
  13. package/hooks/blocking/config/prose_style_enforcement_constants.py +4 -2
  14. package/hooks/blocking/config/test_prose_style_enforcement_constants.py +5 -1
  15. package/hooks/blocking/precommit_code_rules_gate.py +8 -43
  16. package/hooks/blocking/state_description_blocker.py +1 -7
  17. package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +0 -1
  18. package/hooks/blocking/test_code_rules_enforcer_dispatch_wiring.py +0 -8
  19. package/hooks/blocking/test_code_rules_enforcer_module_docstring_roster.py +11 -112
  20. package/hooks/blocking/test_code_rules_enforcer_narrow_edit.py +0 -1
  21. package/hooks/blocking/test_code_rules_enforcer_split_entry_1.py +1 -18
  22. package/hooks/blocking/test_code_rules_shared.py +12 -0
  23. package/hooks/blocking/test_precommit_code_rules_gate.py +32 -179
  24. package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +0 -1
  25. package/hooks/blocking/test_state_description_blocker.py +6 -4
  26. package/hooks/blocking/test_stop_dispatcher.py +5 -29
  27. package/hooks/hooks_constants/AGENTS.md +1 -6
  28. package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +0 -1
  29. package/hooks/hooks_constants/code_rules_enforcer_constants.py +3 -0
  30. package/hooks/hooks_constants/messages.py +0 -2
  31. package/hooks/hooks_constants/precommit_code_rules_gate_constants.py +3 -17
  32. package/hooks/hooks_constants/stop_dispatcher_constants.py +0 -2
  33. package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +0 -1
  34. package/hooks/hooks_constants/test_code_rules_enforcer_constants.py +7 -0
  35. package/hooks/hooks_constants/test_messages.py +5 -3
  36. package/hooks/hooks_constants/test_stop_dispatcher_constants.py +0 -2
  37. package/package.json +1 -1
  38. package/rules/AGENTS.md +3 -6
  39. package/rules/claims-as-quotes.md +0 -10
  40. package/rules/code-standards.md +6 -6
  41. package/rules/explore-thoroughly.md +0 -1
  42. package/rules/failure-blast-radius.md +0 -8
  43. package/rules/falsify-before-green.md +0 -8
  44. package/rules/file-global-constants.md +2 -2
  45. package/rules/filesystem-search.md +1 -1
  46. package/rules/git-workflow.md +1 -9
  47. package/rules/hedging-claims.md +2 -6
  48. package/rules/long-horizon-autonomy.md +1 -1
  49. package/rules/measurement-denominators.md +0 -9
  50. package/rules/research-mode.md +0 -6
  51. package/rules/verify-before-asking.md +0 -5
  52. package/rules/verify-runtime-state.md +0 -5
  53. package/scripts/codex_compat_materializer.py +0 -12
  54. package/scripts/sync_to_cursor/rules.py +0 -10
  55. package/scripts/tests/test_engine.py +0 -1
  56. package/scripts/tests/test_rules.py +0 -1
  57. package/scripts/tests/test_sync_to_cursor.py +0 -1
  58. package/system-prompts/software-engineer.xml +3 -3
  59. package/hooks/blocking/code_rules_dead_argparse_argument.py +0 -554
  60. package/hooks/blocking/code_rules_dead_config_field.py +0 -568
  61. package/hooks/blocking/code_rules_dead_dataclass_field.py +0 -348
  62. package/hooks/blocking/code_rules_dead_module_constant.py +0 -757
  63. package/hooks/blocking/code_rules_dead_split_branch.py +0 -225
  64. package/hooks/blocking/code_rules_mock_completeness.py +0 -295
  65. package/hooks/blocking/code_rules_scope_binding.py +0 -151
  66. package/hooks/blocking/code_rules_unused_imports.py +0 -197
  67. package/hooks/blocking/hedging_language_blocker.py +0 -221
  68. package/hooks/blocking/intent_only_ending_blocker.py +0 -148
  69. package/hooks/blocking/test_code_rules_enforcer_dead_argparse_argument.py +0 -534
  70. package/hooks/blocking/test_code_rules_enforcer_dead_config_field.py +0 -846
  71. package/hooks/blocking/test_code_rules_enforcer_dead_dataclass_field.py +0 -507
  72. package/hooks/blocking/test_code_rules_enforcer_dead_module_constant.py +0 -679
  73. package/hooks/blocking/test_code_rules_enforcer_dead_module_constant_alias.py +0 -133
  74. package/hooks/blocking/test_code_rules_enforcer_dead_module_constant_read_cap.py +0 -103
  75. package/hooks/blocking/test_code_rules_enforcer_dead_split_branch.py +0 -105
  76. package/hooks/blocking/test_code_rules_enforcer_docstring_args_span_scope.py +0 -425
  77. package/hooks/blocking/test_code_rules_enforcer_docstring_cardinal_family.py +0 -176
  78. package/hooks/blocking/test_code_rules_enforcer_docstring_delegation_summary.py +0 -385
  79. package/hooks/blocking/test_code_rules_enforcer_docstring_fallback_branch.py +0 -398
  80. package/hooks/blocking/test_code_rules_enforcer_docstring_field_runmode_outcome.py +0 -129
  81. package/hooks/blocking/test_code_rules_enforcer_docstring_inline_literal_claim.py +0 -93
  82. package/hooks/blocking/test_code_rules_enforcer_docstring_length_constant_superlative.py +0 -198
  83. package/hooks/blocking/test_code_rules_enforcer_docstring_mark_glyph_enumeration.py +0 -262
  84. package/hooks/blocking/test_code_rules_enforcer_docstring_no_consumer.py +0 -93
  85. package/hooks/blocking/test_code_rules_enforcer_docstring_no_network.py +0 -115
  86. package/hooks/blocking/test_code_rules_enforcer_docstring_raises_largezipfile.py +0 -226
  87. package/hooks/blocking/test_code_rules_enforcer_docstring_returns_plural_cardinality.py +0 -207
  88. package/hooks/blocking/test_code_rules_enforcer_docstring_step_dispatch.py +0 -262
  89. package/hooks/blocking/test_code_rules_enforcer_docstring_type_checking_gate.py +0 -164
  90. package/hooks/blocking/test_code_rules_enforcer_docstring_unguarded_payload.py +0 -188
  91. package/hooks/blocking/test_code_rules_enforcer_import_block_sort.py +0 -157
  92. package/hooks/blocking/test_code_rules_enforcer_split_mocks_1.py +0 -303
  93. package/hooks/blocking/test_code_rules_enforcer_split_mocks_2.py +0 -111
  94. package/hooks/blocking/test_code_rules_enforcer_unused_imports.py +0 -656
  95. package/hooks/blocking/test_hedging_language_blocker.py +0 -261
  96. package/hooks/blocking/test_intent_only_ending_blocker.py +0 -209
  97. package/hooks/hooks_constants/dead_argparse_argument_constants.py +0 -28
  98. package/hooks/hooks_constants/dead_config_field_constants.py +0 -39
  99. package/hooks/hooks_constants/dead_dataclass_field_constants.py +0 -25
  100. package/hooks/hooks_constants/dead_module_constant_constants.py +0 -30
  101. package/hooks/hooks_constants/hedging_uncertainty_constants.py +0 -42
  102. package/hooks/hooks_constants/test_dispatcher_constants_docstrings.py +0 -44
  103. package/rules/conservative-action.md +0 -17
  104. package/rules/context7.md +0 -8
  105. package/rules/few-words.md +0 -3
  106. package/rules/parallel-tools.md +0 -23
@@ -1,133 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import importlib.util
4
- import os
5
- import shutil
6
- import stat
7
- import tempfile
8
- from collections.abc import Callable, Iterator
9
- from pathlib import Path
10
-
11
- import pytest
12
-
13
- ENFORCER_PATH = Path(__file__).resolve().parent / "code_rules_enforcer.py"
14
- specification = importlib.util.spec_from_file_location("code_rules_enforcer", ENFORCER_PATH)
15
- assert specification is not None and specification.loader is not None
16
- code_rules_enforcer = importlib.util.module_from_spec(specification)
17
- specification.loader.exec_module(code_rules_enforcer)
18
-
19
- CONSTANTS_BODY = 'MEDIUM_TERMINAL = "terminal"\nMEDIUM_CODE = "code"\nMEDIUM_TEXT = "text"\n'
20
-
21
-
22
- def _strip_read_only_and_retry(
23
- removal_function: Callable[[str], object],
24
- target_path: str,
25
- _exc_info: BaseException,
26
- ) -> None:
27
- try:
28
- os.chmod(target_path, stat.S_IWRITE)
29
- removal_function(target_path)
30
- except OSError:
31
- pass
32
-
33
-
34
- @pytest.fixture
35
- def neutral_root() -> Iterator[Path]:
36
- """Yield a temp directory whose path carries no ``test_`` segment.
37
-
38
- ::
39
-
40
- tmp_path (pytest default) -> embeds "test_..." in its name
41
- -> is_test_file() misreads the path
42
- mkdtemp(prefix="deadconst-") -> no "test_" segment -> reads as
43
- a production path ok
44
-
45
- A ``.git`` marker is planted at the root so the cross-tree widening
46
- resolves the repository root to this synthetic tree.
47
- """
48
- neutral_directory = Path(tempfile.mkdtemp(prefix="deadconst-")).resolve()
49
- (neutral_directory / ".git").mkdir()
50
- try:
51
- yield neutral_directory
52
- finally:
53
- shutil.rmtree(neutral_directory, onexc=_strip_read_only_and_retry)
54
-
55
-
56
- def _check(source: str, file_path: str) -> list[str]:
57
- return code_rules_enforcer.check_dead_module_constants(source, file_path)
58
-
59
-
60
- def _build_constants_package(
61
- workflow_directory: Path,
62
- constants_body: str,
63
- consumer_body: str,
64
- ) -> Path:
65
- constants_package = workflow_directory / "report_constants"
66
- constants_package.mkdir(parents=True)
67
- (constants_package / "__init__.py").write_text("", encoding="utf-8")
68
- constants_path = constants_package / "render_report_constants.py"
69
- constants_path.write_text(constants_body, encoding="utf-8")
70
- (workflow_directory / "render_report.py").write_text(consumer_body, encoding="utf-8")
71
- return constants_path
72
-
73
-
74
- def _assert_alias_read_constants_live(issues: list[str]) -> None:
75
- assert not any(
76
- "MEDIUM_TERMINAL" in each_issue or "MEDIUM_CODE" in each_issue for each_issue in issues
77
- ), f"A constant read as attribute of an imported module stays live, got: {issues}"
78
- assert any("MEDIUM_TEXT" in each_issue for each_issue in issues), (
79
- f"A constant read by no module must still be flagged, got: {issues}"
80
- )
81
-
82
-
83
- def test_does_not_flag_constant_read_via_from_import_module_alias_attribute(
84
- neutral_root: Path,
85
- ) -> None:
86
- consumer_body = (
87
- "from report_constants import render_report_constants as constants\n"
88
- "\n"
89
- "def panel_class(medium: str) -> str:\n"
90
- " if medium == constants.MEDIUM_TERMINAL:\n"
91
- " return 'terminal'\n"
92
- " return 'code' if medium == constants.MEDIUM_CODE else 'other'\n"
93
- )
94
- constants_path = _build_constants_package(
95
- neutral_root / "workflow", CONSTANTS_BODY, consumer_body
96
- )
97
- _assert_alias_read_constants_live(_check(CONSTANTS_BODY, str(constants_path)))
98
-
99
-
100
- def test_does_not_flag_constant_read_via_import_as_alias_attribute(
101
- neutral_root: Path,
102
- ) -> None:
103
- consumer_body = (
104
- "import report_constants.render_report_constants as constants\n"
105
- "\n"
106
- "def label(medium: str) -> str:\n"
107
- " if medium == constants.MEDIUM_TERMINAL:\n"
108
- " return 'terminal'\n"
109
- " return 'code' if medium == constants.MEDIUM_CODE else 'other'\n"
110
- )
111
- constants_path = _build_constants_package(
112
- neutral_root / "workflow", CONSTANTS_BODY, consumer_body
113
- )
114
- _assert_alias_read_constants_live(_check(CONSTANTS_BODY, str(constants_path)))
115
-
116
-
117
- def test_does_not_flag_constant_read_via_plain_module_name_attribute(
118
- neutral_root: Path,
119
- ) -> None:
120
- consumer_body = (
121
- "from report_constants import render_report_constants\n"
122
- "\n"
123
- "def label(medium: str) -> str:\n"
124
- " if medium == render_report_constants.MEDIUM_TERMINAL:\n"
125
- " return 'terminal'\n"
126
- " if medium == render_report_constants.MEDIUM_CODE:\n"
127
- " return 'code'\n"
128
- " return 'other'\n"
129
- )
130
- constants_path = _build_constants_package(
131
- neutral_root / "workflow", CONSTANTS_BODY, consumer_body
132
- )
133
- _assert_alias_read_constants_live(_check(CONSTANTS_BODY, str(constants_path)))
@@ -1,103 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import importlib.util
4
- import os
5
- import shutil
6
- import stat
7
- import tempfile
8
- from collections.abc import Callable, Iterator
9
- from pathlib import Path
10
-
11
- import pytest
12
-
13
- ENFORCER_PATH = Path(__file__).resolve().parent / "code_rules_enforcer.py"
14
- specification = importlib.util.spec_from_file_location("code_rules_enforcer", ENFORCER_PATH)
15
- assert specification is not None and specification.loader is not None
16
- code_rules_enforcer = importlib.util.module_from_spec(specification)
17
- specification.loader.exec_module(code_rules_enforcer)
18
-
19
-
20
- def _strip_read_only_and_retry(
21
- removal_function: Callable[[str], object],
22
- target_path: str,
23
- _exc_info: BaseException,
24
- ) -> None:
25
- try:
26
- os.chmod(target_path, stat.S_IWRITE)
27
- removal_function(target_path)
28
- except OSError:
29
- pass
30
-
31
-
32
- @pytest.fixture
33
- def neutral_root() -> Iterator[Path]:
34
- """Yield a temp directory whose path carries no ``test_`` segment.
35
-
36
- ::
37
-
38
- tmp_path (pytest default) -> embeds "test_..." in its name
39
- -> is_test_file() misreads every
40
- synthetic constants path
41
- mkdtemp(prefix="deadconst-") -> no "test_" segment
42
- -> reads as a production path ok
43
-
44
- A ``.git`` marker is planted at the root so the cross-tree widening
45
- resolves the repository root to this synthetic tree.
46
- """
47
- neutral_directory = Path(tempfile.mkdtemp(prefix="deadconst-")).resolve()
48
- (neutral_directory / ".git").mkdir()
49
- try:
50
- yield neutral_directory
51
- finally:
52
- shutil.rmtree(neutral_directory, onexc=_strip_read_only_and_retry)
53
-
54
-
55
- def _check(source: str, file_path: str) -> list[str]:
56
- return code_rules_enforcer.check_dead_module_constants(source, file_path)
57
-
58
-
59
- def _write_noise_modules(directory: Path, count: int) -> None:
60
- directory.mkdir(parents=True)
61
- for each_index in range(count):
62
- (directory / f"mod_{each_index}.py").write_text(
63
- "def noop() -> int:\n return 1\n", encoding="utf-8"
64
- )
65
-
66
-
67
- def test_widened_scan_bounds_total_disk_reads_on_noncandidate_flood(
68
- neutral_root: Path, monkeypatch: pytest.MonkeyPatch
69
- ) -> None:
70
- """A read-attempt cap stops the widened pass from reading every sibling.
71
-
72
- ::
73
-
74
- MAX_SCAN_ROOT_READ_COUNT = 3, 50 non-candidate noise files
75
- ok: read_text() called a bounded number of times (< 50)
76
- flag: read_text() called once per noise file (== 50)
77
-
78
- Without the cap, ``_read_candidate_source`` opens and reads every
79
- repository ``.py`` file's full text before testing it for the module
80
- stem, so disk-read cost scales with repository size regardless of how
81
- quickly the file cap would otherwise stop the parse-and-collect work.
82
- """
83
- monkeypatch.setattr("code_rules_dead_module_constant.MAX_SCAN_ROOT_READ_COUNT", 3)
84
- package_directory = neutral_root / "pkg"
85
- package_directory.mkdir(parents=True)
86
- constants_body = 'DEAD_EXPORTED = "x"\n__all__ = ["DEAD_EXPORTED"]\n'
87
- constants_path = package_directory / "settings_constants.py"
88
- constants_path.write_text(constants_body, encoding="utf-8")
89
- _write_noise_modules(neutral_root / "noise", 50)
90
- read_count = 0
91
- original_read_text = Path.read_text
92
-
93
- def counting_read_text(self: Path, *positional: object, **keyword: object) -> str:
94
- nonlocal read_count
95
- read_count += 1
96
- return original_read_text(self, *positional, **keyword) # type: ignore[arg-type] # forwards positional/keyword args mypy cannot resolve
97
-
98
- monkeypatch.setattr(Path, "read_text", counting_read_text)
99
- _check(constants_body, str(constants_path))
100
- assert read_count < 50, (
101
- "A read-count cap must stop the widened pass from reading every "
102
- f"non-candidate sibling's full text, got {read_count} reads across 50 noise files"
103
- )
@@ -1,105 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import importlib.util
4
- from pathlib import Path
5
-
6
- ENFORCER_PATH = Path(__file__).resolve().parent / "code_rules_enforcer.py"
7
- specification = importlib.util.spec_from_file_location("code_rules_enforcer", ENFORCER_PATH)
8
- assert specification is not None and specification.loader is not None
9
- code_rules_enforcer = importlib.util.module_from_spec(specification)
10
- specification.loader.exec_module(code_rules_enforcer)
11
-
12
- PRODUCTION_PATH = "C:/project/pkg/menu_info_colors.py"
13
-
14
-
15
- def _check(source: str) -> list[str]:
16
- return code_rules_enforcer.check_dead_split_truthiness_branch(source, PRODUCTION_PATH)
17
-
18
-
19
- def test_flags_split_truthiness_else_arm() -> None:
20
- source = (
21
- "def _extract_uid_prefix(uid: str) -> str:\n"
22
- ' all_parts = uid.split("_")\n'
23
- " if len(all_parts) > 2:\n"
24
- ' return "_".join(all_parts[:3])\n'
25
- " return all_parts[0] if all_parts else uid\n"
26
- )
27
- issues = _check(source)
28
- assert len(issues) == 1
29
- assert "all_parts" in issues[0]
30
- assert "Line 5" in issues[0]
31
-
32
-
33
- def test_flags_negated_guard_dead_body() -> None:
34
- source = (
35
- "def first_segment(path: str) -> str:\n"
36
- ' all_segments = path.split("/")\n'
37
- " if not all_segments:\n"
38
- " return path\n"
39
- " return all_segments[0]\n"
40
- )
41
- issues = _check(source)
42
- assert len(issues) == 1
43
- assert "all_segments" in issues[0]
44
-
45
-
46
- def test_does_not_flag_split_without_separator() -> None:
47
- source = (
48
- "def first_token(text: str) -> str:\n"
49
- " all_parts = text.split()\n"
50
- " return all_parts[0] if all_parts else text\n"
51
- )
52
- assert _check(source) == []
53
-
54
-
55
- def test_does_not_flag_length_comparison_guard() -> None:
56
- source = (
57
- "def prefix(uid: str) -> str:\n"
58
- ' all_parts = uid.split("_")\n'
59
- " if len(all_parts) > 1:\n"
60
- " return all_parts[0]\n"
61
- " return uid\n"
62
- )
63
- assert _check(source) == []
64
-
65
-
66
- def test_does_not_flag_when_name_reassigned() -> None:
67
- source = (
68
- "def normalize(uid: str) -> str:\n"
69
- ' all_parts = uid.split("_")\n'
70
- " all_parts = [each_part.strip() for each_part in all_parts]\n"
71
- " return all_parts[0] if all_parts else uid\n"
72
- )
73
- assert _check(source) == []
74
-
75
-
76
- def test_does_not_flag_when_name_is_parameter() -> None:
77
- source = (
78
- "def shape(all_parts: list[str]) -> str:\n"
79
- ' all_parts = "x".split("_")\n'
80
- ' return all_parts[0] if all_parts else ""\n'
81
- )
82
- assert _check(source) == []
83
-
84
-
85
- def test_does_not_flag_attribute_receiver_split() -> None:
86
- source = (
87
- "def first(s: object) -> object:\n"
88
- ' parts = s.str.split(",")\n'
89
- " return parts[0] if parts else 0\n"
90
- )
91
- assert _check(source) == []
92
-
93
-
94
- def test_does_not_flag_in_test_file() -> None:
95
- source = (
96
- "def helper(uid: str) -> str:\n"
97
- ' all_parts = uid.split("_")\n'
98
- " return all_parts[0] if all_parts else uid\n"
99
- )
100
- assert (
101
- code_rules_enforcer.check_dead_split_truthiness_branch(
102
- source, "C:/project/pkg/test_thing.py"
103
- )
104
- == []
105
- )