thailint 0.15.5__tar.gz

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 (226) hide show
  1. thailint-0.15.5/CHANGELOG.md +577 -0
  2. thailint-0.15.5/LICENSE +21 -0
  3. thailint-0.15.5/PKG-INFO +187 -0
  4. thailint-0.15.5/README.md +150 -0
  5. thailint-0.15.5/pyproject.toml +254 -0
  6. thailint-0.15.5/src/__init__.py +62 -0
  7. thailint-0.15.5/src/analyzers/__init__.py +24 -0
  8. thailint-0.15.5/src/analyzers/ast_utils.py +54 -0
  9. thailint-0.15.5/src/analyzers/rust_base.py +155 -0
  10. thailint-0.15.5/src/analyzers/rust_context.py +141 -0
  11. thailint-0.15.5/src/analyzers/typescript_base.py +152 -0
  12. thailint-0.15.5/src/api.py +118 -0
  13. thailint-0.15.5/src/cli/__init__.py +30 -0
  14. thailint-0.15.5/src/cli/__main__.py +22 -0
  15. thailint-0.15.5/src/cli/config.py +480 -0
  16. thailint-0.15.5/src/cli/config_merge.py +241 -0
  17. thailint-0.15.5/src/cli/linters/__init__.py +67 -0
  18. thailint-0.15.5/src/cli/linters/code_patterns.py +270 -0
  19. thailint-0.15.5/src/cli/linters/code_smells.py +342 -0
  20. thailint-0.15.5/src/cli/linters/documentation.py +83 -0
  21. thailint-0.15.5/src/cli/linters/performance.py +287 -0
  22. thailint-0.15.5/src/cli/linters/shared.py +331 -0
  23. thailint-0.15.5/src/cli/linters/structure.py +327 -0
  24. thailint-0.15.5/src/cli/linters/structure_quality.py +328 -0
  25. thailint-0.15.5/src/cli/main.py +120 -0
  26. thailint-0.15.5/src/cli/utils.py +395 -0
  27. thailint-0.15.5/src/cli_main.py +37 -0
  28. thailint-0.15.5/src/config.py +378 -0
  29. thailint-0.15.5/src/core/__init__.py +17 -0
  30. thailint-0.15.5/src/core/base.py +224 -0
  31. thailint-0.15.5/src/core/cli_utils.py +223 -0
  32. thailint-0.15.5/src/core/config_parser.py +129 -0
  33. thailint-0.15.5/src/core/constants.py +54 -0
  34. thailint-0.15.5/src/core/linter_utils.py +257 -0
  35. thailint-0.15.5/src/core/python_lint_rule.py +101 -0
  36. thailint-0.15.5/src/core/registry.py +95 -0
  37. thailint-0.15.5/src/core/rule_discovery.py +195 -0
  38. thailint-0.15.5/src/core/types.py +96 -0
  39. thailint-0.15.5/src/core/violation_builder.py +185 -0
  40. thailint-0.15.5/src/core/violation_utils.py +69 -0
  41. thailint-0.15.5/src/formatters/__init__.py +22 -0
  42. thailint-0.15.5/src/formatters/sarif.py +202 -0
  43. thailint-0.15.5/src/linter_config/__init__.py +13 -0
  44. thailint-0.15.5/src/linter_config/directive_markers.py +109 -0
  45. thailint-0.15.5/src/linter_config/ignore.py +334 -0
  46. thailint-0.15.5/src/linter_config/loader.py +100 -0
  47. thailint-0.15.5/src/linter_config/pattern_utils.py +65 -0
  48. thailint-0.15.5/src/linter_config/rule_matcher.py +89 -0
  49. thailint-0.15.5/src/linters/__init__.py +4 -0
  50. thailint-0.15.5/src/linters/collection_pipeline/__init__.py +90 -0
  51. thailint-0.15.5/src/linters/collection_pipeline/any_all_analyzer.py +281 -0
  52. thailint-0.15.5/src/linters/collection_pipeline/ast_utils.py +40 -0
  53. thailint-0.15.5/src/linters/collection_pipeline/config.py +75 -0
  54. thailint-0.15.5/src/linters/collection_pipeline/continue_analyzer.py +94 -0
  55. thailint-0.15.5/src/linters/collection_pipeline/detector.py +360 -0
  56. thailint-0.15.5/src/linters/collection_pipeline/filter_map_analyzer.py +402 -0
  57. thailint-0.15.5/src/linters/collection_pipeline/linter.py +420 -0
  58. thailint-0.15.5/src/linters/collection_pipeline/suggestion_builder.py +130 -0
  59. thailint-0.15.5/src/linters/cqs/__init__.py +54 -0
  60. thailint-0.15.5/src/linters/cqs/config.py +55 -0
  61. thailint-0.15.5/src/linters/cqs/function_analyzer.py +201 -0
  62. thailint-0.15.5/src/linters/cqs/input_detector.py +139 -0
  63. thailint-0.15.5/src/linters/cqs/linter.py +159 -0
  64. thailint-0.15.5/src/linters/cqs/output_detector.py +84 -0
  65. thailint-0.15.5/src/linters/cqs/python_analyzer.py +54 -0
  66. thailint-0.15.5/src/linters/cqs/types.py +82 -0
  67. thailint-0.15.5/src/linters/cqs/typescript_cqs_analyzer.py +61 -0
  68. thailint-0.15.5/src/linters/cqs/typescript_function_analyzer.py +192 -0
  69. thailint-0.15.5/src/linters/cqs/typescript_input_detector.py +203 -0
  70. thailint-0.15.5/src/linters/cqs/typescript_output_detector.py +117 -0
  71. thailint-0.15.5/src/linters/cqs/violation_builder.py +94 -0
  72. thailint-0.15.5/src/linters/dry/__init__.py +23 -0
  73. thailint-0.15.5/src/linters/dry/base_token_analyzer.py +83 -0
  74. thailint-0.15.5/src/linters/dry/block_filter.py +365 -0
  75. thailint-0.15.5/src/linters/dry/block_grouper.py +63 -0
  76. thailint-0.15.5/src/linters/dry/cache.py +266 -0
  77. thailint-0.15.5/src/linters/dry/cache_query.py +65 -0
  78. thailint-0.15.5/src/linters/dry/config.py +177 -0
  79. thailint-0.15.5/src/linters/dry/config_loader.py +44 -0
  80. thailint-0.15.5/src/linters/dry/constant.py +92 -0
  81. thailint-0.15.5/src/linters/dry/constant_matcher.py +223 -0
  82. thailint-0.15.5/src/linters/dry/constant_violation_builder.py +98 -0
  83. thailint-0.15.5/src/linters/dry/deduplicator.py +120 -0
  84. thailint-0.15.5/src/linters/dry/duplicate_storage.py +64 -0
  85. thailint-0.15.5/src/linters/dry/file_analyzer.py +92 -0
  86. thailint-0.15.5/src/linters/dry/inline_ignore.py +131 -0
  87. thailint-0.15.5/src/linters/dry/linter.py +298 -0
  88. thailint-0.15.5/src/linters/dry/python_analyzer.py +289 -0
  89. thailint-0.15.5/src/linters/dry/python_constant_extractor.py +100 -0
  90. thailint-0.15.5/src/linters/dry/single_statement_detector.py +417 -0
  91. thailint-0.15.5/src/linters/dry/storage_initializer.py +42 -0
  92. thailint-0.15.5/src/linters/dry/token_hasher.py +173 -0
  93. thailint-0.15.5/src/linters/dry/typescript_analyzer.py +278 -0
  94. thailint-0.15.5/src/linters/dry/typescript_constant_extractor.py +138 -0
  95. thailint-0.15.5/src/linters/dry/typescript_statement_detector.py +255 -0
  96. thailint-0.15.5/src/linters/dry/typescript_value_extractor.py +70 -0
  97. thailint-0.15.5/src/linters/dry/violation_builder.py +78 -0
  98. thailint-0.15.5/src/linters/dry/violation_filter.py +95 -0
  99. thailint-0.15.5/src/linters/dry/violation_generator.py +231 -0
  100. thailint-0.15.5/src/linters/file_header/__init__.py +24 -0
  101. thailint-0.15.5/src/linters/file_header/atemporal_detector.py +105 -0
  102. thailint-0.15.5/src/linters/file_header/base_parser.py +93 -0
  103. thailint-0.15.5/src/linters/file_header/bash_parser.py +66 -0
  104. thailint-0.15.5/src/linters/file_header/config.py +140 -0
  105. thailint-0.15.5/src/linters/file_header/css_parser.py +70 -0
  106. thailint-0.15.5/src/linters/file_header/field_validator.py +72 -0
  107. thailint-0.15.5/src/linters/file_header/linter.py +309 -0
  108. thailint-0.15.5/src/linters/file_header/markdown_parser.py +130 -0
  109. thailint-0.15.5/src/linters/file_header/python_parser.py +42 -0
  110. thailint-0.15.5/src/linters/file_header/typescript_parser.py +73 -0
  111. thailint-0.15.5/src/linters/file_header/violation_builder.py +79 -0
  112. thailint-0.15.5/src/linters/file_placement/__init__.py +31 -0
  113. thailint-0.15.5/src/linters/file_placement/config_loader.py +88 -0
  114. thailint-0.15.5/src/linters/file_placement/directory_matcher.py +84 -0
  115. thailint-0.15.5/src/linters/file_placement/linter.py +444 -0
  116. thailint-0.15.5/src/linters/file_placement/path_resolver.py +61 -0
  117. thailint-0.15.5/src/linters/file_placement/pattern_matcher.py +90 -0
  118. thailint-0.15.5/src/linters/file_placement/pattern_validator.py +125 -0
  119. thailint-0.15.5/src/linters/file_placement/rule_checker.py +234 -0
  120. thailint-0.15.5/src/linters/file_placement/violation_factory.py +177 -0
  121. thailint-0.15.5/src/linters/lazy_ignores/__init__.py +43 -0
  122. thailint-0.15.5/src/linters/lazy_ignores/config.py +74 -0
  123. thailint-0.15.5/src/linters/lazy_ignores/directive_utils.py +164 -0
  124. thailint-0.15.5/src/linters/lazy_ignores/header_parser.py +177 -0
  125. thailint-0.15.5/src/linters/lazy_ignores/linter.py +158 -0
  126. thailint-0.15.5/src/linters/lazy_ignores/matcher.py +168 -0
  127. thailint-0.15.5/src/linters/lazy_ignores/python_analyzer.py +209 -0
  128. thailint-0.15.5/src/linters/lazy_ignores/rule_id_utils.py +180 -0
  129. thailint-0.15.5/src/linters/lazy_ignores/skip_detector.py +298 -0
  130. thailint-0.15.5/src/linters/lazy_ignores/types.py +71 -0
  131. thailint-0.15.5/src/linters/lazy_ignores/typescript_analyzer.py +146 -0
  132. thailint-0.15.5/src/linters/lazy_ignores/violation_builder.py +135 -0
  133. thailint-0.15.5/src/linters/lbyl/__init__.py +31 -0
  134. thailint-0.15.5/src/linters/lbyl/config.py +63 -0
  135. thailint-0.15.5/src/linters/lbyl/linter.py +67 -0
  136. thailint-0.15.5/src/linters/lbyl/pattern_detectors/__init__.py +53 -0
  137. thailint-0.15.5/src/linters/lbyl/pattern_detectors/base.py +63 -0
  138. thailint-0.15.5/src/linters/lbyl/pattern_detectors/dict_key_detector.py +107 -0
  139. thailint-0.15.5/src/linters/lbyl/pattern_detectors/division_check_detector.py +232 -0
  140. thailint-0.15.5/src/linters/lbyl/pattern_detectors/file_exists_detector.py +220 -0
  141. thailint-0.15.5/src/linters/lbyl/pattern_detectors/hasattr_detector.py +119 -0
  142. thailint-0.15.5/src/linters/lbyl/pattern_detectors/isinstance_detector.py +119 -0
  143. thailint-0.15.5/src/linters/lbyl/pattern_detectors/len_check_detector.py +173 -0
  144. thailint-0.15.5/src/linters/lbyl/pattern_detectors/none_check_detector.py +146 -0
  145. thailint-0.15.5/src/linters/lbyl/pattern_detectors/string_validator_detector.py +145 -0
  146. thailint-0.15.5/src/linters/lbyl/python_analyzer.py +215 -0
  147. thailint-0.15.5/src/linters/lbyl/violation_builder.py +354 -0
  148. thailint-0.15.5/src/linters/magic_numbers/__init__.py +48 -0
  149. thailint-0.15.5/src/linters/magic_numbers/config.py +82 -0
  150. thailint-0.15.5/src/linters/magic_numbers/context_analyzer.py +249 -0
  151. thailint-0.15.5/src/linters/magic_numbers/linter.py +462 -0
  152. thailint-0.15.5/src/linters/magic_numbers/python_analyzer.py +64 -0
  153. thailint-0.15.5/src/linters/magic_numbers/typescript_analyzer.py +215 -0
  154. thailint-0.15.5/src/linters/magic_numbers/typescript_ignore_checker.py +81 -0
  155. thailint-0.15.5/src/linters/magic_numbers/violation_builder.py +98 -0
  156. thailint-0.15.5/src/linters/method_property/__init__.py +49 -0
  157. thailint-0.15.5/src/linters/method_property/config.py +138 -0
  158. thailint-0.15.5/src/linters/method_property/linter.py +414 -0
  159. thailint-0.15.5/src/linters/method_property/python_analyzer.py +473 -0
  160. thailint-0.15.5/src/linters/method_property/violation_builder.py +119 -0
  161. thailint-0.15.5/src/linters/nesting/__init__.py +91 -0
  162. thailint-0.15.5/src/linters/nesting/config.py +63 -0
  163. thailint-0.15.5/src/linters/nesting/linter.py +178 -0
  164. thailint-0.15.5/src/linters/nesting/python_analyzer.py +93 -0
  165. thailint-0.15.5/src/linters/nesting/typescript_analyzer.py +111 -0
  166. thailint-0.15.5/src/linters/nesting/typescript_function_extractor.py +130 -0
  167. thailint-0.15.5/src/linters/nesting/violation_builder.py +140 -0
  168. thailint-0.15.5/src/linters/performance/__init__.py +91 -0
  169. thailint-0.15.5/src/linters/performance/config.py +43 -0
  170. thailint-0.15.5/src/linters/performance/constants.py +49 -0
  171. thailint-0.15.5/src/linters/performance/linter.py +149 -0
  172. thailint-0.15.5/src/linters/performance/python_analyzer.py +365 -0
  173. thailint-0.15.5/src/linters/performance/regex_analyzer.py +312 -0
  174. thailint-0.15.5/src/linters/performance/regex_linter.py +139 -0
  175. thailint-0.15.5/src/linters/performance/typescript_analyzer.py +236 -0
  176. thailint-0.15.5/src/linters/performance/violation_builder.py +160 -0
  177. thailint-0.15.5/src/linters/print_statements/__init__.py +53 -0
  178. thailint-0.15.5/src/linters/print_statements/config.py +78 -0
  179. thailint-0.15.5/src/linters/print_statements/linter.py +413 -0
  180. thailint-0.15.5/src/linters/print_statements/python_analyzer.py +153 -0
  181. thailint-0.15.5/src/linters/print_statements/typescript_analyzer.py +125 -0
  182. thailint-0.15.5/src/linters/print_statements/violation_builder.py +96 -0
  183. thailint-0.15.5/src/linters/srp/__init__.py +99 -0
  184. thailint-0.15.5/src/linters/srp/class_analyzer.py +117 -0
  185. thailint-0.15.5/src/linters/srp/config.py +82 -0
  186. thailint-0.15.5/src/linters/srp/heuristics.py +123 -0
  187. thailint-0.15.5/src/linters/srp/linter.py +233 -0
  188. thailint-0.15.5/src/linters/srp/metrics_evaluator.py +47 -0
  189. thailint-0.15.5/src/linters/srp/python_analyzer.py +107 -0
  190. thailint-0.15.5/src/linters/srp/typescript_analyzer.py +75 -0
  191. thailint-0.15.5/src/linters/srp/typescript_metrics_calculator.py +150 -0
  192. thailint-0.15.5/src/linters/srp/violation_builder.py +117 -0
  193. thailint-0.15.5/src/linters/stateless_class/__init__.py +25 -0
  194. thailint-0.15.5/src/linters/stateless_class/config.py +58 -0
  195. thailint-0.15.5/src/linters/stateless_class/linter.py +349 -0
  196. thailint-0.15.5/src/linters/stateless_class/python_analyzer.py +290 -0
  197. thailint-0.15.5/src/linters/stringly_typed/__init__.py +36 -0
  198. thailint-0.15.5/src/linters/stringly_typed/config.py +189 -0
  199. thailint-0.15.5/src/linters/stringly_typed/context_filter.py +451 -0
  200. thailint-0.15.5/src/linters/stringly_typed/function_call_violation_builder.py +135 -0
  201. thailint-0.15.5/src/linters/stringly_typed/ignore_checker.py +100 -0
  202. thailint-0.15.5/src/linters/stringly_typed/ignore_utils.py +51 -0
  203. thailint-0.15.5/src/linters/stringly_typed/linter.py +376 -0
  204. thailint-0.15.5/src/linters/stringly_typed/python/__init__.py +33 -0
  205. thailint-0.15.5/src/linters/stringly_typed/python/analyzer.py +348 -0
  206. thailint-0.15.5/src/linters/stringly_typed/python/call_tracker.py +175 -0
  207. thailint-0.15.5/src/linters/stringly_typed/python/comparison_tracker.py +257 -0
  208. thailint-0.15.5/src/linters/stringly_typed/python/condition_extractor.py +134 -0
  209. thailint-0.15.5/src/linters/stringly_typed/python/conditional_detector.py +179 -0
  210. thailint-0.15.5/src/linters/stringly_typed/python/constants.py +21 -0
  211. thailint-0.15.5/src/linters/stringly_typed/python/match_analyzer.py +94 -0
  212. thailint-0.15.5/src/linters/stringly_typed/python/validation_detector.py +189 -0
  213. thailint-0.15.5/src/linters/stringly_typed/python/variable_extractor.py +96 -0
  214. thailint-0.15.5/src/linters/stringly_typed/storage.py +620 -0
  215. thailint-0.15.5/src/linters/stringly_typed/storage_initializer.py +45 -0
  216. thailint-0.15.5/src/linters/stringly_typed/typescript/__init__.py +28 -0
  217. thailint-0.15.5/src/linters/stringly_typed/typescript/analyzer.py +157 -0
  218. thailint-0.15.5/src/linters/stringly_typed/typescript/call_tracker.py +335 -0
  219. thailint-0.15.5/src/linters/stringly_typed/typescript/comparison_tracker.py +378 -0
  220. thailint-0.15.5/src/linters/stringly_typed/violation_generator.py +419 -0
  221. thailint-0.15.5/src/orchestrator/__init__.py +9 -0
  222. thailint-0.15.5/src/orchestrator/core.py +471 -0
  223. thailint-0.15.5/src/orchestrator/language_detector.py +83 -0
  224. thailint-0.15.5/src/templates/thailint_config_template.yaml +354 -0
  225. thailint-0.15.5/src/utils/__init__.py +4 -0
  226. thailint-0.15.5/src/utils/project_root.py +206 -0
@@ -0,0 +1,577 @@
1
+ # Changelog
2
+
3
+ **Purpose**: Version history and release notes for all thailint package versions
4
+
5
+ **Scope**: All public releases, API changes, features, bug fixes, and breaking changes
6
+
7
+ **Overview**: Maintains comprehensive version history following Keep a Changelog format. Documents
8
+ all notable changes in each release including new features, bug fixes, breaking changes,
9
+ deprecations, and security updates. Organized by version with release dates. Supports
10
+ automated changelog extraction for GitHub releases and user upgrade planning.
11
+
12
+ **Dependencies**: Semantic versioning (semver.org), Keep a Changelog format (keepachangelog.com)
13
+
14
+ **Exports**: Release history, upgrade guides, breaking change documentation
15
+
16
+ **Related**: pyproject.toml (version configuration), GitHub releases, docs/releasing.md
17
+
18
+ **Implementation**: Keep a Changelog 1.1.0 format with semantic versioning and organized change categories
19
+
20
+ All notable changes to this project will be documented in this file.
21
+
22
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
23
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
24
+
25
+ ## [Unreleased]
26
+
27
+ ### Added
28
+
29
+ - **Stateless Class Linter** - Detect Python classes without state that should be module-level functions
30
+
31
+ ## [0.15.4] - 2026-01-26
32
+
33
+ ### Added
34
+
35
+ - **Inline Justifications for Lazy-Ignores** (#147) - Allow inline justifications directly next to ignore statements
36
+ - Syntax: `# noqa: PLR0912 - state machine inherently complex`
37
+ - Delimiter: ` - ` (space-dash-space) followed by justification text
38
+ - Inline justifications take precedence over header-based Suppressions
39
+ - Minimum justification length: 10 characters (configurable)
40
+ - New config options: `allow_inline_justifications`, `min_justification_length`
41
+ - Supports all ignore types: noqa, type:ignore, pylint:disable, nosec, pyright:ignore
42
+ - 27 new tests for inline justification functionality
43
+
44
+ ## [0.15.3] - 2026-01-26
45
+
46
+ ### Fixed
47
+
48
+ - **DRY Linter**: Ignore directives (`# thailint: ignore-start dry` / `ignore-end`) now work correctly for both duplicate code and duplicate constant detection (#144)
49
+ - AST-based detection of classes without `__init__`/`__new__` constructors
50
+ - Detects classes without instance state (`self.attr` assignments)
51
+ - Excludes ABC, Protocol, and decorated classes (legitimate patterns)
52
+ - Excludes classes with class-level attributes
53
+ - Minimum 2 methods required to flag (avoids false positives on simple wrappers)
54
+ - CLI command: `thailint stateless-class src/`
55
+ - JSON and SARIF output formats
56
+ - Configuration via `.thailint.yaml` with `min_methods` and `ignore` options
57
+ - Self-dogfooded: 23 violations in thai-lint codebase were fixed
58
+ - 28 tests (15 detector + 13 CLI) with 100% pass rate
59
+ - Documentation: `docs/stateless-class-linter.md`
60
+
61
+ - **Project Root Detection System** - Three-level precedence system for accurate configuration and ignore pattern resolution
62
+ - `--project-root` CLI option for explicit project root specification (highest priority)
63
+ - Automatic project root inference from `--config` path (config's parent directory becomes project root)
64
+ - Auto-detection fallback that walks up from file location to find markers (`.git`, `.thailint.yaml`, `pyproject.toml`)
65
+ - Priority order: `--project-root` > config inference > auto-detection
66
+ - Click path validation (exists, is directory) with helpful error messages
67
+ - All paths resolved to absolute paths immediately for consistency
68
+
69
+ - **Docker Sibling Directory Support** - Solves critical Docker use case where config and code are in separate directories
70
+ - Explicit project root specification: `docker run -v $(pwd):/workspace thailint --project-root /workspace/root magic-numbers /workspace/backend/`
71
+ - Automatic config path inference: `docker run -v $(pwd):/workspace thailint --config /workspace/root/.thailint.yaml magic-numbers /workspace/backend/`
72
+ - Monorepo support with shared configuration across multiple projects
73
+ - CI/CD-friendly with explicit paths preventing auto-detection issues
74
+
75
+ - **Enhanced Configuration System**
76
+ - Config loading now respects project root context
77
+ - Ignore patterns resolve relative to project root (not file location)
78
+ - Config search paths: explicit `--config` > project-root/.thailint.yaml > auto-detected locations
79
+ - Pyprojroot fallback for test environment compatibility
80
+
81
+ - **Test Suite**
82
+ - 42 tests for project root detection (29 new + 13 updated, 100% passing)
83
+ - `tests/unit/test_cli_project_root.py` - Explicit `--project-root` tests (15 tests)
84
+ - `tests/unit/test_cli_config_inference.py` - Config path inference tests (14 tests)
85
+ - Priority order tests verifying explicit > inferred > auto-detection
86
+ - Error handling tests for invalid paths (doesn't exist, is file not directory)
87
+ - Integration tests with real directory structures
88
+
89
+ ### Changed
90
+
91
+ - **CLI Commands** - All linter commands now accept `--project-root` option
92
+ - `thailint magic-numbers --project-root PATH [TARGET]`
93
+ - `thailint nesting --project-root PATH [TARGET]`
94
+ - `thailint srp --project-root PATH [TARGET]`
95
+ - `thailint file-placement --project-root PATH [TARGET]`
96
+ - All commands support combined usage: `--project-root` with `--config`
97
+
98
+ - **Orchestrator Initialization** - Now accepts explicit project root parameter
99
+ - `Orchestrator(project_root=Path, config_path=Path)` signature
100
+ - Project root passed from CLI to orchestrator for all linting operations
101
+ - Config loading uses project root context for path resolution
102
+
103
+ - **Path Resolution** - All ignore patterns resolve relative to project root
104
+ - Previous behavior: patterns resolved relative to file being linted
105
+ - New behavior: patterns resolved relative to project root directory
106
+ - More predictable and consistent ignore pattern matching
107
+ - Better Docker compatibility with volume mounts
108
+
109
+ ### Documentation
110
+
111
+ - **README.md** - Added comprehensive Docker sibling directory examples
112
+ - "Docker with Sibling Directories" section (lines 171-207)
113
+ - "Docker with Sibling Directories (Advanced)" section (lines 1071-1107)
114
+ - Directory structure examples and use cases
115
+ - Priority order explanation with multiple solution approaches
116
+
117
+ - **CLI Reference** (docs/cli-reference.md)
118
+ - Complete `--project-root` option documentation (lines 120-170)
119
+ - Enhanced `--config` section explaining automatic project root inference (lines 92-118)
120
+ - Use case examples: Docker, monorepos, CI/CD, ignore patterns
121
+ - Error handling examples and exit codes
122
+ - Priority order documentation
123
+
124
+ - **Troubleshooting Guide** (docs/troubleshooting.md)
125
+ - New "Docker sibling directory structure not working" section (lines 754-856)
126
+ - Problem symptoms and root cause explanation
127
+ - Three solution approaches ranked by recommendation
128
+ - Debugging steps with test commands
129
+ - Cross-references to related documentation
130
+
131
+ - **Technical Architecture** (.ai/docs/python-cli-architecture.md)
132
+ - New "Project Root Detection" component documentation (section 2)
133
+ - Architecture diagram updated with project root detection layer
134
+ - Design decisions and implementation patterns
135
+ - Testing strategy and related components
136
+ - Docker use case examples and configuration integration
137
+
138
+ ### Fixed
139
+
140
+ - **Docker Sibling Directory Issue** - Config and code can now be in separate, non-nested directories
141
+ - Previous: Only worked when code was nested under config directory
142
+ - Fixed: Works with any directory structure using `--project-root` or config inference
143
+ - Ignore patterns now resolve correctly in Docker volume mount scenarios
144
+
145
+ - **Ignore Pattern Resolution** - Patterns now resolve consistently relative to project root
146
+ - Previous: Resolved relative to file being linted (inconsistent behavior)
147
+ - Fixed: Resolved relative to project root (predictable, consistent)
148
+ - Especially important for Docker and monorepo scenarios
149
+
150
+ - **Test Environment Compatibility** - Added pyprojroot fallback for pytest environments
151
+ - Tests can run in isolated temporary directories
152
+ - Auto-detection gracefully handles test scenarios without project markers
153
+ - No impact on production code behavior
154
+
155
+ ### Infrastructure
156
+
157
+ - Test suite execution time: All tests pass in <120ms (optimized for fast feedback)
158
+ - TDD approach: RED tests → GREEN implementation → Documentation
159
+ - Pre-commit hooks validated for all changes
160
+ - Zero regressions in existing functionality (13 existing tests updated, all passing)
161
+
162
+ ## [0.2.1] - 2025-10-09
163
+
164
+ **Docker Path Validation Fix** - Fixes critical Docker image bug where file-specific linting failed due to premature path validation.
165
+
166
+ ### Fixed
167
+
168
+ - **Docker Path Validation** - Removed Click's `exists=True` parameter that validated paths before Docker volumes were mounted
169
+ - All linter commands now work with file paths in Docker: `docker run -v $(pwd):/data thailint nesting /data/file.py`
170
+ - Better error messages when paths don't exist, with Docker usage hints
171
+ - Manual path validation happens after argument parsing, compatible with both CLI and Docker contexts
172
+
173
+ ### Changed
174
+
175
+ - Path validation moved from Click argument parsing to execution functions
176
+ - Added `_validate_paths_exist()` helper function with user-friendly error messages
177
+
178
+ ## [0.3.0] - TBD
179
+
180
+ **Single Responsibility Principle (SRP) Linter Release** - Adds comprehensive SRP violation detection for Python and TypeScript code. Uses heuristic-based analysis with configurable thresholds for method count, lines of code, and responsibility keywords. Includes language-specific configurations and extensive refactoring pattern documentation.
181
+
182
+ ### Added
183
+
184
+ - **SRP Linter** - Complete Single Responsibility Principle violation detection
185
+ - Heuristic-based analysis using method count, LOC, and keyword detection
186
+ - Configurable thresholds: `max_methods` (default: 7), `max_loc` (default: 200)
187
+ - Language-specific thresholds for Python, TypeScript, and JavaScript
188
+ - Responsibility keyword detection (Manager, Handler, Processor, Utility, Helper)
189
+ - AST-based analysis using Python `ast` module and `tree-sitter-typescript`
190
+ - Helpful violation messages with refactoring suggestions
191
+
192
+ - **CLI Command: `thailint srp`**
193
+ - `thailint srp [PATH]` - Check files for SRP violations
194
+ - `--max-methods N` - Override method count threshold
195
+ - `--max-loc N` - Override lines of code threshold
196
+ - `--config PATH` - Use specific config file
197
+ - `--format json/text` - Output format selection
198
+ - `--help` - Comprehensive command documentation
199
+
200
+ - **Library API**
201
+ - `srp_lint(path, config)` - Convenience function
202
+ - `SRPRule` - Direct rule class for advanced usage
203
+ - `from src import srp_lint, SRPRule` - Exported in package
204
+
205
+ - **Comprehensive Documentation**
206
+ - `docs/srp-linter.md` - Complete SRP linter guide
207
+ - Configuration examples and best practices
208
+ - 4 refactoring patterns with before/after code examples
209
+ - CI/CD integration examples (GitHub Actions, pre-commit hooks)
210
+ - Troubleshooting guide and common issues
211
+ - Real-world refactoring examples
212
+
213
+ - **Language-Specific Configuration**
214
+ - Python: More strict thresholds (8 methods, 200 LOC)
215
+ - TypeScript: More lenient thresholds (10 methods, 250 LOC) for type verbosity
216
+ - JavaScript: Balanced thresholds (10 methods, 225 LOC)
217
+ - Configurable keyword list for responsibility detection
218
+
219
+ - **Test Suite**
220
+ - 91 tests for SRP linter (100% passing)
221
+ - Python SRP tests (20 tests)
222
+ - TypeScript SRP tests (20 tests)
223
+ - Configuration tests (10 tests)
224
+ - Integration tests (13 tests)
225
+ - Edge case tests (10 tests)
226
+ - Violation message tests (8 tests)
227
+ - Ignore directive tests (10 tests)
228
+
229
+ - **Refactoring Patterns Documentation**
230
+ - Extract Class pattern (split god classes into focused classes)
231
+ - Split Configuration/Logic pattern (separate concerns)
232
+ - Extract Language-Specific Logic pattern (per-language analyzers)
233
+ - Utility Module pattern (group related helpers)
234
+
235
+ ### Changed
236
+
237
+ - **Code Quality Improvements**
238
+ - Refactored 6 classes with SRP violations
239
+ - Applied Extract Class pattern to large classes
240
+ - Improved modularity and maintainability
241
+ - Zero SRP violations in codebase
242
+
243
+ - **README Updates**
244
+ - Added comprehensive SRP linter section with examples
245
+ - Updated feature list with SRP capabilities
246
+ - Added refactoring patterns and examples
247
+
248
+ ### Fixed
249
+
250
+ - Language-specific configuration loading for SRP thresholds
251
+ - Config priority: language-specific → top-level → built-in defaults
252
+
253
+ ### Documentation
254
+
255
+ - Complete SRP linter guide (`docs/srp-linter.md`)
256
+ - Updated CLI reference with SRP command
257
+ - Configuration examples for SRP rules
258
+ - 4 refactoring patterns with code examples
259
+ - Real-world refactoring case studies
260
+
261
+ ### Infrastructure
262
+
263
+ - Updated Makefile with `just lint-solid` target
264
+ - Integrated SRP checks into quality gates
265
+ - CI/CD ready (proper exit codes and JSON output)
266
+
267
+ ## [0.2.0] - 2025-10-07
268
+
269
+ **Nesting Depth Linter Release** - Adds comprehensive nesting depth analysis for Python and TypeScript code. Includes AST-based analysis with tree-sitter, configurable depth limits, and extensive refactoring patterns. Validated on the thai-lint codebase (zero violations after refactoring 23 functions).
270
+
271
+ ### Added
272
+
273
+ - **Nesting Depth Linter** - Complete nesting depth analysis for Python and TypeScript
274
+ - AST-based depth calculation using Python `ast` module and `tree-sitter-typescript`
275
+ - Configurable `max_nesting_depth` (default: 4, thai-lint uses: 3)
276
+ - Detects excessive nesting in if/for/while/with/try/match (Python) and if/for/while/try/switch (TypeScript)
277
+ - Helpful violation messages with refactoring suggestions
278
+ - Depth calculation starts at 1 for function body (matches industry standards)
279
+
280
+ - **CLI Command: `thai-lint nesting`**
281
+ - `thai-lint nesting [PATH]` - Check files for excessive nesting
282
+ - `--max-depth N` - Override configured max depth
283
+ - `--config PATH` - Use specific config file
284
+ - `--format json/text` - Output format selection
285
+ - `--help` - Comprehensive command documentation
286
+
287
+ - **Library API**
288
+ - `nesting_lint(path, max_nesting_depth=4)` - Convenience function
289
+ - `NestingDepthRule` - Direct rule class for advanced usage
290
+ - `from src import nesting_lint, NestingDepthRule` - Exported in package
291
+
292
+ - **Comprehensive Documentation**
293
+ - `docs/nesting-linter.md` - 400+ line comprehensive guide
294
+ - Configuration examples and best practices
295
+ - 5 refactoring patterns with before/after code examples
296
+ - Case study results and time estimates
297
+ - CI/CD integration examples (GitHub Actions, pre-commit hooks)
298
+ - Troubleshooting guide and common issues
299
+
300
+ - **Example Code**
301
+ - `examples/nesting_usage.py` - Library API usage example
302
+ - Configuration templates in docs
303
+
304
+ - **Test Suite**
305
+ - 76 tests for nesting linter (100% passing)
306
+ - Python nesting tests (15 tests)
307
+ - TypeScript nesting tests (15 tests)
308
+ - Configuration tests (8 tests)
309
+ - Integration tests (12 tests)
310
+ - Edge case tests (8 tests)
311
+ - Total project tests: 317 (100% passing, up from 221)
312
+
313
+ - **Refactoring Patterns Documentation**
314
+ - Guard clauses (early returns) - Used in 7 functions
315
+ - Extract method pattern - Used in 13 functions
316
+ - Dispatch pattern (replace if-elif chains) - Used in 5 functions
317
+ - Flatten error handling - Used in 6 functions
318
+ - Invert conditions - Pattern documented
319
+
320
+ ### Changed
321
+
322
+ - **Code Quality Improvements via Dogfooding**
323
+ - Refactored 23 functions with excessive nesting (18 in src/, 5 in tests/examples)
324
+ - Reduced max nesting depth from 4 to 3 project-wide
325
+ - All functions now comply with strict depth limit
326
+ - Improved readability and maintainability across codebase
327
+ - Zero nesting violations in production code
328
+
329
+ - **Test Coverage**
330
+ - Increased from 87% to 90% overall coverage
331
+ - Added 96 new tests (221 → 317)
332
+ - 100% coverage on nesting analyzer modules
333
+
334
+ - **README Updates**
335
+ - Added comprehensive nesting linter section with examples
336
+ - Updated feature list with nesting capabilities
337
+ - Added refactoring patterns and real-world results
338
+ - Updated test badges (317/317 passing, 90% coverage)
339
+
340
+ - **Dependencies**
341
+ - Added `tree-sitter ^0.25.2` for AST parsing
342
+ - Added `tree-sitter-typescript ^0.23.2` for TypeScript support
343
+ - Pure Python solution (no Node.js required)
344
+
345
+ ### Fixed
346
+
347
+ - Ignore directive parser now supports TypeScript comments (`//` and `/* */`)
348
+ - Block ignore directives (`thailint: ignore-start` / `ignore-end`) working correctly
349
+ - Rule matching supports prefix patterns (e.g., "nesting" matches "nesting.excessive-depth")
350
+
351
+ ### Performance
352
+
353
+ - Single file analysis: ~10-30ms (well under 100ms target)
354
+ - 100 files: ~500ms (under 2s target)
355
+ - 1000 files: ~2-3s (under 10s target)
356
+ - AST parsing optimized with caching
357
+
358
+ ### Documentation
359
+
360
+ - Complete nesting linter guide (`docs/nesting-linter.md`)
361
+ - Updated CLI reference with nesting command
362
+ - Configuration examples for nesting rules
363
+ - 5 refactoring patterns with code examples
364
+ - Codebase refactoring case study
365
+
366
+ ### Validation: Codebase Refactoring
367
+
368
+ **Baseline Assessment:**
369
+ - 23 violations (depth 4, max configured: 3)
370
+ - Files: src/cli.py (6), src/config.py (5), orchestrator (3), others (9)
371
+
372
+ **Refactoring Applied:**
373
+ - Time: ~4 hours for 23 functions (~10 min/function average)
374
+ - Patterns: Extract method (13), Guard clauses (7), Dispatch (5), Flatten (6)
375
+ - Tests: 317/317 passing (100%)
376
+ - Quality: Pylint 10.00/10, all complexity A-grade
377
+
378
+ **Results:**
379
+ - Zero nesting violations
380
+ - Improved code readability
381
+ - No functionality broken
382
+ - All integration tests passing
383
+
384
+ ### Infrastructure
385
+
386
+ - Updated Makefile with `just lint-nesting` target
387
+ - Integrated nesting checks into `just lint-full`
388
+ - CI/CD ready (proper exit codes and JSON output)
389
+
390
+ ## [0.1.0] - 2025-10-06
391
+
392
+ **Initial Alpha Release**
393
+
394
+ ### Breaking Changes
395
+
396
+ **Configuration Format Update**: Multi-Linter Top-Level Sections
397
+
398
+ The configuration format has been restructured to support multiple linters with separate top-level sections. This prepares the project for future linters while maintaining a clean separation of concerns.
399
+
400
+ **Old Format** (v0.1.0 and earlier):
401
+ ```yaml
402
+ # .thailint.yaml
403
+ directories:
404
+ src/:
405
+ allow:
406
+ - "^src/.*\\.py$"
407
+ global_patterns:
408
+ deny:
409
+ - pattern: ".*\\.tmp$"
410
+ reason: "No temp files"
411
+ ```
412
+
413
+ **New Format** (v0.2.0+):
414
+ ```yaml
415
+ # .thailint.yaml
416
+ file-placement:
417
+ directories:
418
+ src/:
419
+ allow:
420
+ - "^src/.*\\.py$"
421
+ global_patterns:
422
+ deny:
423
+ - pattern: ".*\\.tmp$"
424
+ reason: "No temp files"
425
+ ```
426
+
427
+ **Migration Steps**:
428
+ 1. Wrap your entire file-placement configuration under a `file-placement:` top-level key
429
+ 2. Use hyphens (`file-placement`) not underscores (`file_placement`)
430
+ 3. Indent all existing configuration one level
431
+ 4. Update any `.thailint.json` files similarly
432
+
433
+ **Rationale**: This change allows multiple linters to coexist cleanly. Future linters like `code-quality:` and `security:` will have their own top-level sections, following the pattern of tools like `pyproject.toml`.
434
+
435
+ ### Added
436
+ - Example configuration files (`.thailint.yaml.example`, `.thailint.json.example`)
437
+ - Documentation for multi-linter configuration format
438
+
439
+ ### Changed
440
+ - Configuration schema now uses top-level linter sections
441
+ - File placement linter looks for config under `file-placement` key (hyphen, not underscore)
442
+
443
+ ### Deprecated
444
+ - Old flat configuration format (still works in v0.1.x but will be removed in v1.0.0)
445
+
446
+ ## [0.1.0] - 2025-10-06
447
+
448
+ **Initial Alpha Release** - This release represents early development status. Core features are functional but the API and configuration formats may change in future releases. Suitable for testing and evaluation.
449
+
450
+ ### Added
451
+ - **Core Framework**: Pluggable linter architecture with base interfaces and rule registry
452
+ - `BaseLintRule` and `BaseLintContext` abstractions
453
+ - Automatic plugin discovery via `RuleRegistry`
454
+ - Binary severity model (ERROR only)
455
+ - Violation dataclass with file, line, rule_id, message, severity
456
+
457
+ - **Configuration System**: Multi-format config loading with 5-level ignore system
458
+ - YAML and JSON config file support
459
+ - 5-level ignore directives (repo, directory, file, method, line)
460
+ - Wildcard rule matching for flexible ignore patterns
461
+ - Config validation and error reporting
462
+
463
+ - **Multi-Language Orchestrator**: File routing and language detection engine
464
+ - Extension-based language detection with shebang fallback
465
+ - Per-language linter routing and execution
466
+ - Context creation and violation aggregation
467
+ - Recursive directory scanning
468
+
469
+ - **File Placement Linter**: Complete file organization linter
470
+ - Pattern-based allow/deny rules with regex support
471
+ - Directory scoping for targeted enforcement
472
+ - Configurable via YAML/JSON with validation
473
+ - Helpful violation suggestions based on file type
474
+ - 81% test coverage, 42/50 tests passing
475
+
476
+ - **CLI Interface**: Professional command-line interface
477
+ - `thailint lint file-placement [PATH]` command
478
+ - Inline JSON rules via `--rules` flag
479
+ - External config via `--config` flag
480
+ - Text and JSON output formats (`--format`)
481
+ - Recursive and non-recursive scanning modes
482
+ - Proper exit codes (0=pass, 1=violations, 2=error)
483
+
484
+ - **Library API**: High-level programmatic interface
485
+ - `Linter` class with config_file and project_root parameters
486
+ - `lint(path, rules=[...])` method for filtered linting
487
+ - Autodiscovery of config files in project root
488
+ - Direct linter imports for backwards compatibility
489
+ - Usage examples (basic, advanced, CI integration)
490
+
491
+ - **Docker Support**: Production-ready containerization
492
+ - Multi-stage Dockerfile with optimized layers
493
+ - Non-root user execution (UID 1000)
494
+ - Volume mounting at `/workspace`
495
+ - 270MB image size (Python 3.11-slim)
496
+ - docker-compose.yml for development workflows
497
+
498
+ - **PyPI Distribution**: Complete packaging and publishing setup
499
+ - PyPI-ready package metadata with classifiers
500
+ - GitHub Actions workflow for automated publishing
501
+ - PyPI Trusted Publishing (OIDC) configuration
502
+ - Automated GitHub releases with changelog extraction
503
+ - MANIFEST.in for clean source distributions
504
+
505
+ - **Comprehensive Testing**: TDD-driven test suite
506
+ - 181+ unit and integration tests
507
+ - 87% overall test coverage
508
+ - pytest with coverage reporting
509
+ - Docker integration tests
510
+
511
+ - **Development Tooling**: Complete quality assurance stack
512
+ - Ruff (linting and formatting)
513
+ - MyPy (strict type checking)
514
+ - Pylint (comprehensive linting)
515
+ - Bandit (security scanning)
516
+ - Xenon (complexity analysis)
517
+ - Pre-commit hooks for quality gates
518
+
519
+ ### Changed
520
+ - Package name: `thai-lint` → `thailint` (PyPI-friendly)
521
+ - CLI command: `thai-lint` → `thailint` (both supported for compatibility)
522
+
523
+ ### Documentation
524
+ - Comprehensive README with installation and usage guides
525
+ - API examples for library usage
526
+ - Docker usage documentation
527
+ - Release process documentation (docs/releasing.md)
528
+ - AI agent guides (.ai/ directory)
529
+
530
+ ### Infrastructure
531
+ - GitHub Actions CI/CD pipelines (test, lint, security)
532
+ - Pre-commit hooks for automated quality checks
533
+ - Poetry-based dependency management
534
+ - Docker multi-stage builds
535
+
536
+ ## [0.0.1] - Initial Development
537
+
538
+ ### Added
539
+ - Basic project structure
540
+ - Poetry configuration
541
+ - Initial CLI scaffold
542
+
543
+ ---
544
+
545
+ ## Version History
546
+
547
+ - **0.1.0** (2025-10-06): Initial alpha release with core feature set
548
+ - **0.0.1**: Initial development version
549
+
550
+ ## Upgrade Guide
551
+
552
+ ### Using Version 0.1.0 (Alpha Release)
553
+
554
+ This is an early alpha release for testing and feedback. Key notes:
555
+
556
+ 1. **CLI Command**: Use `thailint` instead of `thai-lint` (both work)
557
+ 2. **Package Name**: Install as `pip install thailint`
558
+ 3. **Library Import**: Use `from thailint import Linter`
559
+
560
+ ## Contributing
561
+
562
+ When adding entries to this changelog:
563
+
564
+ 1. Add changes to `[Unreleased]` section during development
565
+ 2. Move to versioned section when releasing
566
+ 3. Use categories: Added, Changed, Deprecated, Removed, Fixed, Security
567
+ 4. Include user-facing changes only (not internal refactors)
568
+ 5. Link to issues/PRs when relevant
569
+ 6. Follow Keep a Changelog format
570
+
571
+ ## Links
572
+
573
+ - [PyPI Package](https://pypi.org/project/thailint/)
574
+ - [GitHub Repository](https://github.com/steve-e-jackson/thai-lint)
575
+ - [Issue Tracker](https://github.com/steve-e-jackson/thai-lint/issues)
576
+ - [Keep a Changelog](https://keepachangelog.com/)
577
+ - [Semantic Versioning](https://semver.org/)
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Steve Jackson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.