-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy path.pre-commit-config.yaml
More file actions
284 lines (262 loc) Β· 13.2 KB
/
.pre-commit-config.yaml
File metadata and controls
284 lines (262 loc) Β· 13.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Pre-commit Hooks Configuration
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
#
# Setup (first time):
# uv sync # install all deps including pre-commit
# uv run pre-commit install # install pre-commit hook
# uv run pre-commit install --hook-type pre-push # install pre-push hook
#
# Usage:
# git commit # hooks run automatically
# uv run pre-commit run --all-files # run on all files manually
# SKIP=mypy git commit # skip a slow hook
#
# Auto-evolution (update hook versions):
# uv run pre-commit autoupdate # bump all hooks to latest version
# uv run pre-commit run --all-files # verify after update
#
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
default_stages: [pre-commit]
repos:
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# 1. Standard pre-commit hooks β basic file hygiene (auto-fix)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]
- id: end-of-file-fixer
- id: check-yaml
- id: check-toml
- id: check-json
exclude: ^(htmlcov/|\.vscode/)
- id: check-added-large-files
args: ['--maxkb=500']
- id: check-merge-conflict
- id: debug-statements
- id: detect-private-key
- id: check-ast
# ββ New: comprehensive file & code hygiene ββββββββββ
- id: fix-byte-order-marker
# Auto-removes UTF-8 BOM (auto-fix)
- id: check-builtin-literals
# Detects dict() instead of {}, list() instead of []
- id: check-case-conflict
# Detects files differing only in case (breaks on Windows/macOS)
- id: check-docstring-first
# Prevents code before module docstring
- id: check-executables-have-shebangs
# Scripts with +x must have #!/usr/bin/env
- id: check-shebang-scripts-are-executable
# Scripts with #! must have +x permission
- id: check-symlinks
# Detects broken symlinks
- id: destroyed-symlinks
# Detects symlinks destroyed by git checkout on Windows
- id: check-vcs-permalinks
# Detects non-permanent GitHub links (missing commit hash)
- id: check-illegal-windows-names
# Detects filenames illegal on Windows (CON, PRN, etc.)
- id: mixed-line-ending
args: [--fix=lf]
# Normalizes line endings to LF (auto-fix)
- id: no-commit-to-branch
args: [--branch, main, --branch, master]
# Prevents direct commits to main/master
- id: name-tests-test
args: [--pytest-test-first]
files: ^tests/
# Ensures test files follow test_*.py naming
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# 2. Ruff β ultra-fast linter + formatter (auto-fix enabled)
# Version should stay in sync with pyproject.toml [dependency-groups.dev]
# Run `uv run pre-commit autoupdate` to bump
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.14.13
hooks:
- id: ruff
name: ruff lint (auto-fix)
args: [--fix, --exit-non-zero-on-fix]
types_or: [python, pyi]
- id: ruff-format
name: ruff format (auto-fix)
types_or: [python, pyi]
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# 3. Security & dead code analysis
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- repo: https://github.com/PyCQA/bandit
rev: 1.9.3
hooks:
- id: bandit
name: bandit security scan
args: [-c, pyproject.toml, -ll, --quiet]
# Medium+ severity only. Config in [tool.bandit]
# Skip: SKIP=bandit git commit
- repo: local
hooks:
- id: vulture
name: vulture dead code scan
entry: uv run vulture src/ scripts/ vulture_whitelist.py --min-confidence 80
language: system
types: [python]
pass_filenames: false
files: ^(src|scripts)/
# False positives β vulture_whitelist.py
- id: deptry
name: deptry dependency check
entry: uv run deptry src/
language: system
pass_filenames: false
files: ^(src/|pyproject\.toml)
# Config in [tool.deptry] in pyproject.toml
# semgrep moved to pre-push (see section 5) β too heavy for commit-time (~300-500MB)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# 4. Local hooks β project-specific checks
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- repo: local
hooks:
# ββ Type checking (moved to pre-push β uses 500MB-1GB) ββ
# See section 5 for mypy. Run manually: uv run mypy src/
# ββ Async/sync consistency βββββββββββββββββββββββββββββ
- id: async-test-checker
name: async/sync test consistency
entry: uv run python scripts/check_async_tests.py
language: system
pass_filenames: false
files: ^tests/
# Only runs when test files are staged
# Fix: uv run python scripts/check_async_tests.py --fix
# ββ File hygiene βββββββββββββββββββββββββββββββββββββββ
- id: file-hygiene
name: file hygiene (no temp files)
entry: uv run python scripts/hooks/check_file_hygiene.py
language: system
pass_filenames: false
always_run: true
# ββ Commit size guard ββββββββββββββββββββββββββββββββββ
- id: commit-size-guard
name: commit size guard (β€30 files)
entry: uv run python scripts/hooks/check_commit_size.py
language: system
pass_filenames: false
always_run: true
# Prevents oversized commits; split into focused changes
# Bypass: git commit --no-verify
# ββ MCP tool documentation sync ββββββββββββββββββββββββ
- id: tool-count-sync
name: MCP tool docs sync (auto-fix)
entry: uv run python scripts/hooks/check_tool_sync.py
language: system
pass_filenames: false
files: ^src/pubmed_search/presentation/mcp_server/
# Only runs when MCP server files are modified
# Auto-updates docs and stages them
# ββ Future annotations enforcement (auto-fix) ββββββββββ
- id: future-annotations
name: future annotations (auto-fix)
entry: uv run python scripts/hooks/check_future_annotations.py --fix
language: system
pass_filenames: false
files: ^(src|tests)/.*\.py$
# Ensures 'from __future__ import annotations' in all files
# Auto-inserts after module docstring
# ββ No print() in production code ββββββββββββββββββββββ
- id: no-print-in-src
name: no print() in src/
entry: uv run python scripts/hooks/check_no_print.py
language: system
pass_filenames: false
files: ^src/.*\.py$
# print() β logger.info(). Exceptions: __main__.py
# ββ DDD layer import rules βββββββββββββββββββββββββββββ
- id: ddd-layer-imports
name: DDD layer dependency check
entry: uv run python scripts/hooks/check_ddd_layers.py
language: system
pass_filenames: false
files: ^src/pubmed_search/
# domain/ ββ application/, infrastructure/, presentation/
# application/ ββ infrastructure/, presentation/
# ββ No bare type: ignore βββββββββββββββββββββββββββββββ
- id: no-type-ignore-bare
name: no bare type:ignore
entry: uv run python scripts/hooks/check_type_ignore.py
language: system
pass_filenames: false
files: ^(src|tests)/.*\.py$
# Always specify error code: # type: ignore[assignment]
# ββ MCP tool docstrings ββββββββββββββββββββββββββββββββ
- id: docstring-tools
name: MCP tool docstrings required
entry: uv run python scripts/hooks/check_docstring_tools.py
language: system
pass_filenames: false
files: ^src/pubmed_search/presentation/mcp_server/tools/
# Every @tool function must have docstring β₯10 chars
# ββ No os.environ in inner DDD layers ββββββββββββββββββ
- id: no-env-inner-layers
name: no os.environ in domain/application
entry: uv run python scripts/hooks/check_env_config.py
language: system
pass_filenames: false
files: ^src/pubmed_search/(domain|application|shared)/
# Config via DI container, not os.environ
# ββ Per-source API count guard βββββββββββββββββββββββββ
- id: source-counts-guard
name: per-source API count display guard
entry: uv run python scripts/hooks/check_source_counts.py
language: system
pass_filenames: false
files: ^(src/pubmed_search/presentation/mcp_server/tools/unified(_formatting)?\.py|tests/test_unified_tools\.py|tests/test_pipeline\.py)$
# Ensures per-source API return counts are always displayed
# to the agent (critical for search coverage decisions)
# ββ TODO/FIXME scanner (warning only) ββββββββββββββββββ
- id: todo-scanner
name: TODO/FIXME scanner (warn)
entry: uv run python scripts/hooks/check_todo_scanner.py
language: system
pass_filenames: false
files: ^(src|tests)/.*\.py$
verbose: true
# Non-blocking warning. Set BLOCK_ON_MARKERS=true to block.
# ββ Self-evolution cycle consistency ββββββββββββββββββββ
- id: evolution-cycle
name: instruction β skill β hook consistency
entry: uv run python scripts/hooks/check_evolution_cycle.py
language: system
pass_filenames: false
files: (\.pre-commit-config\.yaml|copilot-instructions\.md|SKILL\.md|CONTRIBUTING\.md|pyproject\.toml|scripts/hooks/)
# Validates the self-evolution cycle:
# Instructions β Skills β Hooks β Validate β Feedback
# Only runs when relevant config/doc files are modified
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# 5. Pre-push hooks β heavier analysis (mypy, semgrep, pytest)
# These are too memory-intensive for pre-commit (~1-2GB total)
# but essential before pushing to remote.
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- repo: https://github.com/semgrep/semgrep
rev: v1.151.0
hooks:
- id: semgrep
name: semgrep security analysis
args: [--config, p/python, --error, --quiet]
stages: [pre-push]
- repo: local
hooks:
- id: mypy
name: mypy type check (src/)
entry: uv run mypy src/
language: system
types: [python]
pass_filenames: false
stages: [pre-push]
- id: pytest
name: pytest (multi-core)
entry: uv run pytest tests/ -n 4 --timeout=60 -q --no-header
language: system
pass_filenames: false
always_run: true
stages: [pre-push]