thailint 0.5.0__tar.gz → 0.8.0__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.
- {thailint-0.5.0 → thailint-0.8.0}/PKG-INFO +155 -3
- {thailint-0.5.0 → thailint-0.8.0}/README.md +153 -1
- {thailint-0.5.0 → thailint-0.8.0}/pyproject.toml +2 -2
- {thailint-0.5.0 → thailint-0.8.0}/src/cli.py +236 -2
- {thailint-0.5.0 → thailint-0.8.0}/src/core/cli_utils.py +16 -1
- {thailint-0.5.0 → thailint-0.8.0}/src/core/registry.py +1 -1
- thailint-0.8.0/src/formatters/__init__.py +22 -0
- thailint-0.8.0/src/formatters/sarif.py +202 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linter_config/loader.py +5 -4
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/block_filter.py +11 -8
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/cache.py +3 -2
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/duplicate_storage.py +5 -4
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/violation_generator.py +1 -1
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/file_header/atemporal_detector.py +11 -11
- thailint-0.8.0/src/linters/file_header/base_parser.py +89 -0
- thailint-0.8.0/src/linters/file_header/bash_parser.py +58 -0
- thailint-0.8.0/src/linters/file_header/config.py +126 -0
- thailint-0.8.0/src/linters/file_header/css_parser.py +70 -0
- thailint-0.8.0/src/linters/file_header/field_validator.py +75 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/file_header/linter.py +113 -121
- thailint-0.8.0/src/linters/file_header/markdown_parser.py +124 -0
- thailint-0.8.0/src/linters/file_header/python_parser.py +42 -0
- thailint-0.8.0/src/linters/file_header/typescript_parser.py +73 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/file_header/violation_builder.py +13 -12
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/file_placement/linter.py +9 -11
- thailint-0.8.0/src/linters/method_property/__init__.py +49 -0
- thailint-0.8.0/src/linters/method_property/config.py +135 -0
- thailint-0.8.0/src/linters/method_property/linter.py +419 -0
- thailint-0.8.0/src/linters/method_property/python_analyzer.py +472 -0
- thailint-0.8.0/src/linters/method_property/violation_builder.py +116 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/print_statements/config.py +7 -12
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/print_statements/linter.py +13 -15
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/print_statements/python_analyzer.py +8 -14
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/print_statements/typescript_analyzer.py +9 -14
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/print_statements/violation_builder.py +12 -14
- thailint-0.5.0/src/linters/file_header/config.py +0 -66
- thailint-0.5.0/src/linters/file_header/field_validator.py +0 -69
- thailint-0.5.0/src/linters/file_header/python_parser.py +0 -86
- {thailint-0.5.0 → thailint-0.8.0}/CHANGELOG.md +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/LICENSE +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/__init__.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/analyzers/__init__.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/analyzers/typescript_base.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/api.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/config.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/core/__init__.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/core/base.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/core/config_parser.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/core/linter_utils.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/core/rule_discovery.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/core/types.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/core/violation_builder.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linter_config/__init__.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linter_config/ignore.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/__init__.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/__init__.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/base_token_analyzer.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/block_grouper.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/cache_query.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/config.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/config_loader.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/deduplicator.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/file_analyzer.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/inline_ignore.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/linter.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/python_analyzer.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/storage_initializer.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/token_hasher.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/typescript_analyzer.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/violation_builder.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/dry/violation_filter.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/file_header/__init__.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/file_placement/__init__.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/file_placement/config_loader.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/file_placement/directory_matcher.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/file_placement/path_resolver.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/file_placement/pattern_matcher.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/file_placement/pattern_validator.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/file_placement/rule_checker.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/file_placement/violation_factory.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/magic_numbers/__init__.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/magic_numbers/config.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/magic_numbers/context_analyzer.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/magic_numbers/linter.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/magic_numbers/python_analyzer.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/magic_numbers/typescript_analyzer.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/magic_numbers/violation_builder.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/nesting/__init__.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/nesting/config.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/nesting/linter.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/nesting/python_analyzer.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/nesting/typescript_analyzer.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/nesting/typescript_function_extractor.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/nesting/violation_builder.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/print_statements/__init__.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/srp/__init__.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/srp/class_analyzer.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/srp/config.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/srp/heuristics.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/srp/linter.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/srp/metrics_evaluator.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/srp/python_analyzer.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/srp/typescript_analyzer.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/srp/typescript_metrics_calculator.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/linters/srp/violation_builder.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/orchestrator/__init__.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/orchestrator/core.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/orchestrator/language_detector.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/templates/thailint_config_template.yaml +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/utils/__init__.py +0 -0
- {thailint-0.5.0 → thailint-0.8.0}/src/utils/project_root.py +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: thailint
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: The AI Linter - Enterprise-grade linting and governance for AI-generated code across multiple languages
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Keywords: linter,ai,code-quality,static-analysis,file-placement,governance,multi-language,cli,docker,python
|
|
8
8
|
Author: Steve Jackson
|
|
9
9
|
Requires-Python: >=3.11,<4.0
|
|
10
|
-
Classifier: Development Status ::
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
11
|
Classifier: Environment :: Console
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -37,9 +37,10 @@ Description-Content-Type: text/markdown
|
|
|
37
37
|
|
|
38
38
|
[](https://opensource.org/licenses/MIT)
|
|
39
39
|
[](https://www.python.org/downloads/)
|
|
40
|
-
[](tests/)
|
|
41
41
|
[](htmlcov/)
|
|
42
42
|
[](https://thai-lint.readthedocs.io/en/latest/?badge=latest)
|
|
43
|
+
[](docs/sarif-output.md)
|
|
43
44
|
|
|
44
45
|
The AI Linter - Enterprise-ready linting and governance for AI-generated code across multiple languages.
|
|
45
46
|
|
|
@@ -73,6 +74,11 @@ thailint complements your existing linting stack by catching the patterns AI too
|
|
|
73
74
|
|
|
74
75
|
### Core Capabilities
|
|
75
76
|
- **File Placement Linting** - Enforce project structure and organization
|
|
77
|
+
- **File Header Linting** - Validate documentation headers in source files
|
|
78
|
+
- Python, TypeScript, JavaScript, Bash, Markdown, CSS support
|
|
79
|
+
- Mandatory field validation (Purpose, Scope, Overview)
|
|
80
|
+
- Atemporal language detection (no dates, "currently", "now")
|
|
81
|
+
- Language-specific header format parsing
|
|
76
82
|
- **Magic Numbers Linting** - Detect unnamed numeric literals that should be constants
|
|
77
83
|
- Python and TypeScript support with AST analysis
|
|
78
84
|
- Context-aware detection (ignores constants, test files, range() usage)
|
|
@@ -92,6 +98,12 @@ thailint complements your existing linting stack by catching the patterns AI too
|
|
|
92
98
|
- Configurable thresholds (lines, tokens, occurrences)
|
|
93
99
|
- Language-specific detection (Python, TypeScript, JavaScript)
|
|
94
100
|
- False positive filtering (keyword args, imports)
|
|
101
|
+
- **Method Property Linting** - Detect methods that should be @property decorators
|
|
102
|
+
- Python AST-based detection
|
|
103
|
+
- get_* prefix detection (Java-style getters)
|
|
104
|
+
- Simple computed value detection
|
|
105
|
+
- Action verb exclusion (to_*, finalize, serialize)
|
|
106
|
+
- Test file detection
|
|
95
107
|
- **Pluggable Architecture** - Easy to extend with custom linters
|
|
96
108
|
- **Multi-Language Support** - Python, TypeScript, JavaScript, and more
|
|
97
109
|
- **Flexible Configuration** - YAML/JSON configs with pattern matching
|
|
@@ -158,11 +170,17 @@ thailint dry .
|
|
|
158
170
|
# Check for magic numbers
|
|
159
171
|
thailint magic-numbers src/
|
|
160
172
|
|
|
173
|
+
# Check file headers
|
|
174
|
+
thailint file-header src/
|
|
175
|
+
|
|
161
176
|
# With config file
|
|
162
177
|
thailint dry --config .thailint.yaml src/
|
|
163
178
|
|
|
164
179
|
# JSON output for CI/CD
|
|
165
180
|
thailint dry --format json src/
|
|
181
|
+
|
|
182
|
+
# SARIF output for GitHub Code Scanning
|
|
183
|
+
thailint nesting --format sarif src/ > results.sarif
|
|
166
184
|
```
|
|
167
185
|
|
|
168
186
|
**New to thailint?** See the **[Quick Start Guide](https://thai-lint.readthedocs.io/en/latest/quick-start/)** for a complete walkthrough including config generation, understanding output, and next steps.
|
|
@@ -869,6 +887,136 @@ def get_ports(): # thailint: ignore[magic-numbers] - Standard ports
|
|
|
869
887
|
|
|
870
888
|
See **[How to Ignore Violations](https://thai-lint.readthedocs.io/en/latest/how-to-ignore-violations/)** and **[Magic Numbers Linter Guide](https://thai-lint.readthedocs.io/en/latest/magic-numbers-linter/)** for complete documentation.
|
|
871
889
|
|
|
890
|
+
## File Header Linter
|
|
891
|
+
|
|
892
|
+
### Overview
|
|
893
|
+
|
|
894
|
+
The file header linter validates that source files have proper documentation headers containing required fields (Purpose, Scope, Overview) and don't use temporal language (dates, "currently", "now"). It enforces consistent documentation patterns across entire codebases.
|
|
895
|
+
|
|
896
|
+
### Why File Headers?
|
|
897
|
+
|
|
898
|
+
File headers serve as **self-documentation** that helps developers (and AI assistants) quickly understand:
|
|
899
|
+
|
|
900
|
+
- **Purpose**: What does this file do?
|
|
901
|
+
- **Scope**: What area of the system does it cover?
|
|
902
|
+
- **Dependencies**: What does it rely on?
|
|
903
|
+
- **Exports**: What does it provide to other modules?
|
|
904
|
+
|
|
905
|
+
### Quick Start
|
|
906
|
+
|
|
907
|
+
```bash
|
|
908
|
+
# Check file headers in current directory
|
|
909
|
+
thailint file-header .
|
|
910
|
+
|
|
911
|
+
# Check specific directory
|
|
912
|
+
thailint file-header src/
|
|
913
|
+
|
|
914
|
+
# Get JSON output
|
|
915
|
+
thailint file-header --format json src/
|
|
916
|
+
|
|
917
|
+
# Get SARIF output for CI/CD
|
|
918
|
+
thailint file-header --format sarif src/ > results.sarif
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
### Configuration
|
|
922
|
+
|
|
923
|
+
Add to `.thailint.yaml`:
|
|
924
|
+
|
|
925
|
+
```yaml
|
|
926
|
+
file-header:
|
|
927
|
+
enabled: true
|
|
928
|
+
mandatory_fields:
|
|
929
|
+
- Purpose
|
|
930
|
+
- Scope
|
|
931
|
+
- Overview
|
|
932
|
+
ignore:
|
|
933
|
+
- "**/__init__.py"
|
|
934
|
+
- "**/migrations/**"
|
|
935
|
+
```
|
|
936
|
+
|
|
937
|
+
### Example Violation
|
|
938
|
+
|
|
939
|
+
**Code without proper header:**
|
|
940
|
+
```python
|
|
941
|
+
import os
|
|
942
|
+
|
|
943
|
+
def process_data():
|
|
944
|
+
pass
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
**Violation messages:**
|
|
948
|
+
```
|
|
949
|
+
src/utils.py:1 - Missing mandatory field: Purpose
|
|
950
|
+
src/utils.py:1 - Missing mandatory field: Scope
|
|
951
|
+
src/utils.py:1 - Missing mandatory field: Overview
|
|
952
|
+
```
|
|
953
|
+
|
|
954
|
+
**Refactored with header:**
|
|
955
|
+
```python
|
|
956
|
+
"""
|
|
957
|
+
Purpose: Data processing utilities for ETL pipeline
|
|
958
|
+
|
|
959
|
+
Scope: Data transformation layer, used by batch processing jobs
|
|
960
|
+
|
|
961
|
+
Overview: Provides data transformation functions for the ETL pipeline.
|
|
962
|
+
Handles parsing, validation, and normalization of incoming data.
|
|
963
|
+
|
|
964
|
+
Dependencies: os, json
|
|
965
|
+
|
|
966
|
+
Exports: process_data(), validate_input(), transform_record()
|
|
967
|
+
"""
|
|
968
|
+
import os
|
|
969
|
+
|
|
970
|
+
def process_data():
|
|
971
|
+
pass
|
|
972
|
+
```
|
|
973
|
+
|
|
974
|
+
### Atemporal Language Detection
|
|
975
|
+
|
|
976
|
+
The linter detects temporal language that becomes stale:
|
|
977
|
+
|
|
978
|
+
**Temporal (flagged):**
|
|
979
|
+
```python
|
|
980
|
+
"""
|
|
981
|
+
Purpose: Authentication module
|
|
982
|
+
|
|
983
|
+
Overview: Currently handles OAuth. This was recently updated.
|
|
984
|
+
Created: 2024-01-15. Will be extended in the future.
|
|
985
|
+
"""
|
|
986
|
+
```
|
|
987
|
+
|
|
988
|
+
**Atemporal (correct):**
|
|
989
|
+
```python
|
|
990
|
+
"""
|
|
991
|
+
Purpose: Authentication module
|
|
992
|
+
|
|
993
|
+
Overview: Handles OAuth authentication with Google and GitHub.
|
|
994
|
+
Implements authorization code flow with PKCE for security.
|
|
995
|
+
"""
|
|
996
|
+
```
|
|
997
|
+
|
|
998
|
+
### Language Support
|
|
999
|
+
|
|
1000
|
+
- **Python**: Module docstrings (`"""..."""`)
|
|
1001
|
+
- **TypeScript/JavaScript**: JSDoc comments (`/** ... */`)
|
|
1002
|
+
- **Bash**: Hash comments after shebang (`# ...`)
|
|
1003
|
+
- **Markdown**: YAML frontmatter (`---...---`)
|
|
1004
|
+
- **CSS/SCSS**: Block comments (`/* ... */`)
|
|
1005
|
+
|
|
1006
|
+
### Ignoring Violations
|
|
1007
|
+
|
|
1008
|
+
```python
|
|
1009
|
+
# File-level ignore
|
|
1010
|
+
# thailint: ignore-file[file-header]
|
|
1011
|
+
|
|
1012
|
+
# Line-level ignore for atemporal violation
|
|
1013
|
+
"""
|
|
1014
|
+
Overview: Created 2024-01-15. # thailint: ignore[file-header]
|
|
1015
|
+
"""
|
|
1016
|
+
```
|
|
1017
|
+
|
|
1018
|
+
See **[How to Ignore Violations](https://thai-lint.readthedocs.io/en/latest/how-to-ignore-violations/)** and **[File Header Linter Guide](https://thai-lint.readthedocs.io/en/latest/file-header-linter/)** for complete documentation.
|
|
1019
|
+
|
|
872
1020
|
## Pre-commit Hooks
|
|
873
1021
|
|
|
874
1022
|
Automate code quality checks before every commit and push with pre-commit hooks.
|
|
@@ -1153,11 +1301,13 @@ docker run --rm -v /path/to/workspace:/workspace \
|
|
|
1153
1301
|
- **[CLI Reference](https://thai-lint.readthedocs.io/en/latest/cli-reference/)** - All CLI commands and options
|
|
1154
1302
|
- **[Deployment Modes](https://thai-lint.readthedocs.io/en/latest/deployment-modes/)** - CLI, Library, and Docker usage
|
|
1155
1303
|
- **[File Placement Linter](https://thai-lint.readthedocs.io/en/latest/file-placement-linter/)** - Detailed linter guide
|
|
1304
|
+
- **[File Header Linter](https://thai-lint.readthedocs.io/en/latest/file-header-linter/)** - File header validation guide
|
|
1156
1305
|
- **[Magic Numbers Linter](https://thai-lint.readthedocs.io/en/latest/magic-numbers-linter/)** - Magic numbers detection guide
|
|
1157
1306
|
- **[Nesting Depth Linter](https://thai-lint.readthedocs.io/en/latest/nesting-linter/)** - Nesting depth analysis guide
|
|
1158
1307
|
- **[SRP Linter](https://thai-lint.readthedocs.io/en/latest/srp-linter/)** - Single Responsibility Principle guide
|
|
1159
1308
|
- **[DRY Linter](https://thai-lint.readthedocs.io/en/latest/dry-linter/)** - Duplicate code detection guide
|
|
1160
1309
|
- **[Pre-commit Hooks](https://thai-lint.readthedocs.io/en/latest/pre-commit-hooks/)** - Automated quality checks
|
|
1310
|
+
- **[SARIF Output Guide](docs/sarif-output.md)** - SARIF format for GitHub Code Scanning and CI/CD
|
|
1161
1311
|
- **[Publishing Guide](https://thai-lint.readthedocs.io/en/latest/releasing/)** - Release and publishing workflow
|
|
1162
1312
|
- **[Publishing Checklist](https://thai-lint.readthedocs.io/en/latest/publishing-checklist/)** - Post-publication validation
|
|
1163
1313
|
|
|
@@ -1168,6 +1318,8 @@ See [`examples/`](examples/) directory for working code:
|
|
|
1168
1318
|
- **[basic_usage.py](examples/basic_usage.py)** - Simple library API usage
|
|
1169
1319
|
- **[advanced_usage.py](examples/advanced_usage.py)** - Advanced patterns and workflows
|
|
1170
1320
|
- **[ci_integration.py](examples/ci_integration.py)** - CI/CD integration example
|
|
1321
|
+
- **[sarif_usage.py](examples/sarif_usage.py)** - SARIF output format examples
|
|
1322
|
+
- **[file_header_usage.py](examples/file_header_usage.py)** - File header validation examples
|
|
1171
1323
|
|
|
1172
1324
|
## Project Structure
|
|
1173
1325
|
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://opensource.org/licenses/MIT)
|
|
4
4
|
[](https://www.python.org/downloads/)
|
|
5
|
-
[](tests/)
|
|
6
6
|
[](htmlcov/)
|
|
7
7
|
[](https://thai-lint.readthedocs.io/en/latest/?badge=latest)
|
|
8
|
+
[](docs/sarif-output.md)
|
|
8
9
|
|
|
9
10
|
The AI Linter - Enterprise-ready linting and governance for AI-generated code across multiple languages.
|
|
10
11
|
|
|
@@ -38,6 +39,11 @@ thailint complements your existing linting stack by catching the patterns AI too
|
|
|
38
39
|
|
|
39
40
|
### Core Capabilities
|
|
40
41
|
- **File Placement Linting** - Enforce project structure and organization
|
|
42
|
+
- **File Header Linting** - Validate documentation headers in source files
|
|
43
|
+
- Python, TypeScript, JavaScript, Bash, Markdown, CSS support
|
|
44
|
+
- Mandatory field validation (Purpose, Scope, Overview)
|
|
45
|
+
- Atemporal language detection (no dates, "currently", "now")
|
|
46
|
+
- Language-specific header format parsing
|
|
41
47
|
- **Magic Numbers Linting** - Detect unnamed numeric literals that should be constants
|
|
42
48
|
- Python and TypeScript support with AST analysis
|
|
43
49
|
- Context-aware detection (ignores constants, test files, range() usage)
|
|
@@ -57,6 +63,12 @@ thailint complements your existing linting stack by catching the patterns AI too
|
|
|
57
63
|
- Configurable thresholds (lines, tokens, occurrences)
|
|
58
64
|
- Language-specific detection (Python, TypeScript, JavaScript)
|
|
59
65
|
- False positive filtering (keyword args, imports)
|
|
66
|
+
- **Method Property Linting** - Detect methods that should be @property decorators
|
|
67
|
+
- Python AST-based detection
|
|
68
|
+
- get_* prefix detection (Java-style getters)
|
|
69
|
+
- Simple computed value detection
|
|
70
|
+
- Action verb exclusion (to_*, finalize, serialize)
|
|
71
|
+
- Test file detection
|
|
60
72
|
- **Pluggable Architecture** - Easy to extend with custom linters
|
|
61
73
|
- **Multi-Language Support** - Python, TypeScript, JavaScript, and more
|
|
62
74
|
- **Flexible Configuration** - YAML/JSON configs with pattern matching
|
|
@@ -123,11 +135,17 @@ thailint dry .
|
|
|
123
135
|
# Check for magic numbers
|
|
124
136
|
thailint magic-numbers src/
|
|
125
137
|
|
|
138
|
+
# Check file headers
|
|
139
|
+
thailint file-header src/
|
|
140
|
+
|
|
126
141
|
# With config file
|
|
127
142
|
thailint dry --config .thailint.yaml src/
|
|
128
143
|
|
|
129
144
|
# JSON output for CI/CD
|
|
130
145
|
thailint dry --format json src/
|
|
146
|
+
|
|
147
|
+
# SARIF output for GitHub Code Scanning
|
|
148
|
+
thailint nesting --format sarif src/ > results.sarif
|
|
131
149
|
```
|
|
132
150
|
|
|
133
151
|
**New to thailint?** See the **[Quick Start Guide](https://thai-lint.readthedocs.io/en/latest/quick-start/)** for a complete walkthrough including config generation, understanding output, and next steps.
|
|
@@ -834,6 +852,136 @@ def get_ports(): # thailint: ignore[magic-numbers] - Standard ports
|
|
|
834
852
|
|
|
835
853
|
See **[How to Ignore Violations](https://thai-lint.readthedocs.io/en/latest/how-to-ignore-violations/)** and **[Magic Numbers Linter Guide](https://thai-lint.readthedocs.io/en/latest/magic-numbers-linter/)** for complete documentation.
|
|
836
854
|
|
|
855
|
+
## File Header Linter
|
|
856
|
+
|
|
857
|
+
### Overview
|
|
858
|
+
|
|
859
|
+
The file header linter validates that source files have proper documentation headers containing required fields (Purpose, Scope, Overview) and don't use temporal language (dates, "currently", "now"). It enforces consistent documentation patterns across entire codebases.
|
|
860
|
+
|
|
861
|
+
### Why File Headers?
|
|
862
|
+
|
|
863
|
+
File headers serve as **self-documentation** that helps developers (and AI assistants) quickly understand:
|
|
864
|
+
|
|
865
|
+
- **Purpose**: What does this file do?
|
|
866
|
+
- **Scope**: What area of the system does it cover?
|
|
867
|
+
- **Dependencies**: What does it rely on?
|
|
868
|
+
- **Exports**: What does it provide to other modules?
|
|
869
|
+
|
|
870
|
+
### Quick Start
|
|
871
|
+
|
|
872
|
+
```bash
|
|
873
|
+
# Check file headers in current directory
|
|
874
|
+
thailint file-header .
|
|
875
|
+
|
|
876
|
+
# Check specific directory
|
|
877
|
+
thailint file-header src/
|
|
878
|
+
|
|
879
|
+
# Get JSON output
|
|
880
|
+
thailint file-header --format json src/
|
|
881
|
+
|
|
882
|
+
# Get SARIF output for CI/CD
|
|
883
|
+
thailint file-header --format sarif src/ > results.sarif
|
|
884
|
+
```
|
|
885
|
+
|
|
886
|
+
### Configuration
|
|
887
|
+
|
|
888
|
+
Add to `.thailint.yaml`:
|
|
889
|
+
|
|
890
|
+
```yaml
|
|
891
|
+
file-header:
|
|
892
|
+
enabled: true
|
|
893
|
+
mandatory_fields:
|
|
894
|
+
- Purpose
|
|
895
|
+
- Scope
|
|
896
|
+
- Overview
|
|
897
|
+
ignore:
|
|
898
|
+
- "**/__init__.py"
|
|
899
|
+
- "**/migrations/**"
|
|
900
|
+
```
|
|
901
|
+
|
|
902
|
+
### Example Violation
|
|
903
|
+
|
|
904
|
+
**Code without proper header:**
|
|
905
|
+
```python
|
|
906
|
+
import os
|
|
907
|
+
|
|
908
|
+
def process_data():
|
|
909
|
+
pass
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
**Violation messages:**
|
|
913
|
+
```
|
|
914
|
+
src/utils.py:1 - Missing mandatory field: Purpose
|
|
915
|
+
src/utils.py:1 - Missing mandatory field: Scope
|
|
916
|
+
src/utils.py:1 - Missing mandatory field: Overview
|
|
917
|
+
```
|
|
918
|
+
|
|
919
|
+
**Refactored with header:**
|
|
920
|
+
```python
|
|
921
|
+
"""
|
|
922
|
+
Purpose: Data processing utilities for ETL pipeline
|
|
923
|
+
|
|
924
|
+
Scope: Data transformation layer, used by batch processing jobs
|
|
925
|
+
|
|
926
|
+
Overview: Provides data transformation functions for the ETL pipeline.
|
|
927
|
+
Handles parsing, validation, and normalization of incoming data.
|
|
928
|
+
|
|
929
|
+
Dependencies: os, json
|
|
930
|
+
|
|
931
|
+
Exports: process_data(), validate_input(), transform_record()
|
|
932
|
+
"""
|
|
933
|
+
import os
|
|
934
|
+
|
|
935
|
+
def process_data():
|
|
936
|
+
pass
|
|
937
|
+
```
|
|
938
|
+
|
|
939
|
+
### Atemporal Language Detection
|
|
940
|
+
|
|
941
|
+
The linter detects temporal language that becomes stale:
|
|
942
|
+
|
|
943
|
+
**Temporal (flagged):**
|
|
944
|
+
```python
|
|
945
|
+
"""
|
|
946
|
+
Purpose: Authentication module
|
|
947
|
+
|
|
948
|
+
Overview: Currently handles OAuth. This was recently updated.
|
|
949
|
+
Created: 2024-01-15. Will be extended in the future.
|
|
950
|
+
"""
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
**Atemporal (correct):**
|
|
954
|
+
```python
|
|
955
|
+
"""
|
|
956
|
+
Purpose: Authentication module
|
|
957
|
+
|
|
958
|
+
Overview: Handles OAuth authentication with Google and GitHub.
|
|
959
|
+
Implements authorization code flow with PKCE for security.
|
|
960
|
+
"""
|
|
961
|
+
```
|
|
962
|
+
|
|
963
|
+
### Language Support
|
|
964
|
+
|
|
965
|
+
- **Python**: Module docstrings (`"""..."""`)
|
|
966
|
+
- **TypeScript/JavaScript**: JSDoc comments (`/** ... */`)
|
|
967
|
+
- **Bash**: Hash comments after shebang (`# ...`)
|
|
968
|
+
- **Markdown**: YAML frontmatter (`---...---`)
|
|
969
|
+
- **CSS/SCSS**: Block comments (`/* ... */`)
|
|
970
|
+
|
|
971
|
+
### Ignoring Violations
|
|
972
|
+
|
|
973
|
+
```python
|
|
974
|
+
# File-level ignore
|
|
975
|
+
# thailint: ignore-file[file-header]
|
|
976
|
+
|
|
977
|
+
# Line-level ignore for atemporal violation
|
|
978
|
+
"""
|
|
979
|
+
Overview: Created 2024-01-15. # thailint: ignore[file-header]
|
|
980
|
+
"""
|
|
981
|
+
```
|
|
982
|
+
|
|
983
|
+
See **[How to Ignore Violations](https://thai-lint.readthedocs.io/en/latest/how-to-ignore-violations/)** and **[File Header Linter Guide](https://thai-lint.readthedocs.io/en/latest/file-header-linter/)** for complete documentation.
|
|
984
|
+
|
|
837
985
|
## Pre-commit Hooks
|
|
838
986
|
|
|
839
987
|
Automate code quality checks before every commit and push with pre-commit hooks.
|
|
@@ -1118,11 +1266,13 @@ docker run --rm -v /path/to/workspace:/workspace \
|
|
|
1118
1266
|
- **[CLI Reference](https://thai-lint.readthedocs.io/en/latest/cli-reference/)** - All CLI commands and options
|
|
1119
1267
|
- **[Deployment Modes](https://thai-lint.readthedocs.io/en/latest/deployment-modes/)** - CLI, Library, and Docker usage
|
|
1120
1268
|
- **[File Placement Linter](https://thai-lint.readthedocs.io/en/latest/file-placement-linter/)** - Detailed linter guide
|
|
1269
|
+
- **[File Header Linter](https://thai-lint.readthedocs.io/en/latest/file-header-linter/)** - File header validation guide
|
|
1121
1270
|
- **[Magic Numbers Linter](https://thai-lint.readthedocs.io/en/latest/magic-numbers-linter/)** - Magic numbers detection guide
|
|
1122
1271
|
- **[Nesting Depth Linter](https://thai-lint.readthedocs.io/en/latest/nesting-linter/)** - Nesting depth analysis guide
|
|
1123
1272
|
- **[SRP Linter](https://thai-lint.readthedocs.io/en/latest/srp-linter/)** - Single Responsibility Principle guide
|
|
1124
1273
|
- **[DRY Linter](https://thai-lint.readthedocs.io/en/latest/dry-linter/)** - Duplicate code detection guide
|
|
1125
1274
|
- **[Pre-commit Hooks](https://thai-lint.readthedocs.io/en/latest/pre-commit-hooks/)** - Automated quality checks
|
|
1275
|
+
- **[SARIF Output Guide](docs/sarif-output.md)** - SARIF format for GitHub Code Scanning and CI/CD
|
|
1126
1276
|
- **[Publishing Guide](https://thai-lint.readthedocs.io/en/latest/releasing/)** - Release and publishing workflow
|
|
1127
1277
|
- **[Publishing Checklist](https://thai-lint.readthedocs.io/en/latest/publishing-checklist/)** - Post-publication validation
|
|
1128
1278
|
|
|
@@ -1133,6 +1283,8 @@ See [`examples/`](examples/) directory for working code:
|
|
|
1133
1283
|
- **[basic_usage.py](examples/basic_usage.py)** - Simple library API usage
|
|
1134
1284
|
- **[advanced_usage.py](examples/advanced_usage.py)** - Advanced patterns and workflows
|
|
1135
1285
|
- **[ci_integration.py](examples/ci_integration.py)** - CI/CD integration example
|
|
1286
|
+
- **[sarif_usage.py](examples/sarif_usage.py)** - SARIF output format examples
|
|
1287
|
+
- **[file_header_usage.py](examples/file_header_usage.py)** - File header validation examples
|
|
1136
1288
|
|
|
1137
1289
|
## Project Structure
|
|
1138
1290
|
|
|
@@ -17,7 +17,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
17
17
|
|
|
18
18
|
[tool.poetry]
|
|
19
19
|
name = "thailint"
|
|
20
|
-
version = "0.
|
|
20
|
+
version = "0.8.0"
|
|
21
21
|
description = "The AI Linter - Enterprise-grade linting and governance for AI-generated code across multiple languages"
|
|
22
22
|
authors = ["Steve Jackson"]
|
|
23
23
|
license = "MIT"
|
|
@@ -38,7 +38,7 @@ keywords = [
|
|
|
38
38
|
"python",
|
|
39
39
|
]
|
|
40
40
|
classifiers = [
|
|
41
|
-
"Development Status ::
|
|
41
|
+
"Development Status :: 4 - Beta",
|
|
42
42
|
"Intended Audience :: Developers",
|
|
43
43
|
"License :: OSI Approved :: MIT License",
|
|
44
44
|
"Programming Language :: Python :: 3",
|