claude-dev-env 8.106.3 → 8.106.4

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.
@@ -62,7 +62,7 @@ Open [details](code-rules/design-and-structure.md) when adding a class or parame
62
62
 
63
63
  ## 7.5 SOLID PRINCIPLES
64
64
 
65
- Apply SRP throughout. Apply OCP, LSP, ISP, and DIP when two concrete implementations share a contract. Keep cohesive classes together.
65
+ Keep a function whole while it reads top to bottom. Split it when the new piece has a second caller or makes the caller easier to read, or when it reaches the 60-line cap the lint and the write-time hook enforce. Apply OCP, LSP, ISP, and DIP when two concrete implementations share a contract. Keep cohesive classes together.
66
66
 
67
67
  Open [details](code-rules/design-and-structure.md) when extracting a responsibility.
68
68
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-dev-env",
3
- "version": "8.106.3",
3
+ "version": "8.106.4",
4
4
  "description": "Claude Code development standards — rules, hooks, agents, commands, and skills",
5
5
  "type": "module",
6
6
  "bin": {
@@ -61,6 +61,9 @@ ALL_CHECK_CATALOG_ENTRIES: tuple[CheckCatalogEntry, ...] = (
61
61
  "paired-test-missing-function",
62
62
  ),
63
63
  CheckCatalogEntry("but exercises nowhere", "paired-test-omitted-function"),
64
+ CheckCatalogEntry(") - consider splitting", "file-length"),
65
+ CheckCatalogEntry(" lines (max ", "function-line-cap"),
66
+ CheckCatalogEntry(" has nesting depth ", "nesting-depth"),
64
67
  )
65
68
 
66
69
  SEVERITY_BREAKING: str = "breaking"
@@ -68,5 +71,8 @@ SEVERITY_SMELL: str = "smell"
68
71
  SEVERITY_BY_CHECK_ID: dict[str, str] = {
69
72
  "code-rules/paired-test-missing-function": SEVERITY_SMELL,
70
73
  "code-rules/paired-test-omitted-function": SEVERITY_SMELL,
74
+ "validators/file-length": SEVERITY_SMELL,
75
+ "validators/function-line-cap": SEVERITY_SMELL,
76
+ "validators/nesting-depth": SEVERITY_SMELL,
71
77
  "test-pairing": SEVERITY_SMELL,
72
78
  }
@@ -18,6 +18,7 @@ from policy_lint.config.check_catalog_constants import (
18
18
  from policy_lint.model import Diagnostic, Severity
19
19
 
20
20
  _BUNDLING_RULE_ID = "code-rules"
21
+ _VALIDATORS_RULE_ID = "validators"
21
22
  _HOOKS_DIRECTORY = Path(__file__).resolve().parents[2] / "hooks"
22
23
  _TEST_FILE_PREFIX = "test_"
23
24
  _PYTHON_GLOB = "*.py"
@@ -82,6 +83,9 @@ ALL_MESSAGE_SAMPLES: tuple[tuple[str, str], ...] = (
82
83
  " already covers another public function in that module",
83
84
  "paired-test-omitted-function",
84
85
  ),
86
+ ("src/app.py:1: File is 412 lines (max 400) - consider splitting", "file-length"),
87
+ ("src/app.py:4: Function 'run' is 37 lines (max 30)", "function-line-cap"),
88
+ ("src/app.py:9: Function 'run' has nesting depth 3 (max 2)", "nesting-depth"),
85
89
  )
86
90
 
87
91
 
@@ -169,6 +173,23 @@ def test_a_paired_test_check_reports_as_a_warning(check_name: str) -> None:
169
173
  assert severity_for_check_id(f"{_BUNDLING_RULE_ID}/{check_name}") is Severity.WARNING
170
174
 
171
175
 
176
+ @pytest.mark.parametrize(
177
+ ("sample_message", "check_name"),
178
+ tuple(
179
+ each_sample
180
+ for each_sample in ALL_MESSAGE_SAMPLES
181
+ if each_sample[1] in ("file-length", "function-line-cap", "nesting-depth")
182
+ ),
183
+ )
184
+ def test_a_validator_smell_reports_as_a_warning(
185
+ sample_message: str, check_name: str
186
+ ) -> None:
187
+ check_id = check_id_for_message(_VALIDATORS_RULE_ID, sample_message)
188
+
189
+ assert check_id == f"{_VALIDATORS_RULE_ID}/{check_name}"
190
+ assert severity_for_check_id(check_id) is Severity.WARNING
191
+
192
+
172
193
  def test_an_unclassified_check_reports_as_an_error() -> None:
173
194
  unclassified_check_id = f"{_BUNDLING_RULE_ID}/{UNCLASSIFIED_CHECK_NAME}"
174
195