mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 19:07:04 +01:00
Also bumps the 16 meta/requirements pins the freshness gate flagged (anthropic 1.5.0, numpy 2.5.3, pytest-randomly 5, flake8-bugbear 26.9.9, ruff 0.16.7, pyright 1.1.414, selenium 4.49.0, hypothesis 6.168.0, lxml 6.1.3, pipdeptree 4.2.5, the two types-* stubs) and Flutter 3.47.3 in meta/.fvmrc. One test still expected the pre-move ~/mcp-servers path. The pre-commit hook fed .zsh files to shfmt and shellcheck, neither of which parses zsh (SC2148/SC1071), so no zsh file could be committed since the hook was tightened on 2026-08-22; those now get `zsh -n` instead. The hook's own shfmt pass also staged its reformat of 8 shell files. CI_GREEN_SKIP because main is red on exactly the dependency-freshness finding this commit fixes, which is the documented use of that flag. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AwtowrowDXx6ccmWVPkCaF
617 lines
26 KiB
YAML
617 lines
26 KiB
YAML
# ==============================================================================
|
|
# Pre-commit Configuration - Multi-language Linting & Formatting
|
|
# ==============================================================================
|
|
# Install: pre-commit install && pre-commit install --hook-type pre-push
|
|
# Fast lint: pre-commit run --all-files (linters only, ~10 s)
|
|
# Full suite: pre-commit run --all-files --hook-stage pre-push (+ tests)
|
|
# Update hooks: pre-commit autoupdate
|
|
# ==============================================================================
|
|
|
|
# Global settings
|
|
default_language_version:
|
|
python: python3
|
|
|
|
# By default every hook runs ONLY at commit-time. Pre-push runs only the
|
|
# hooks that explicitly opt in via `stages: [pre-push]` (currently
|
|
# pytest-coverage + prettier). This keeps `git push` cheap; commit-time
|
|
# already enforces the full lint suite.
|
|
default_stages: [pre-commit]
|
|
|
|
# Fail fast on first error (set to false to see all errors)
|
|
fail_fast: false
|
|
|
|
# Configuration
|
|
ci:
|
|
autofix_commit_msg: "style: auto-fix by pre-commit hooks"
|
|
autoupdate_commit_msg: "chore: update pre-commit hooks"
|
|
|
|
repos:
|
|
# ===========================================================================
|
|
# GENERAL HOOKS - File formatting and validation
|
|
# ===========================================================================
|
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
rev: v4.6.0
|
|
hooks:
|
|
- id: trailing-whitespace
|
|
args: [--markdown-linebreak-ext=md]
|
|
- id: end-of-file-fixer
|
|
- id: check-yaml
|
|
args: [--unsafe]
|
|
- id: check-json
|
|
# Exclude JSONC files (VS Code configs, TypeScript configs)
|
|
exclude: ^(\.vscode/|.*/\.vscode/|.*tsconfig.*\.json)
|
|
- id: check-toml
|
|
- id: check-xml
|
|
- id: check-added-large-files
|
|
args: [--maxkb=2000]
|
|
- id: check-merge-conflict
|
|
- id: check-case-conflict
|
|
- id: check-symlinks
|
|
- id: check-executables-have-shebangs
|
|
- id: check-shebang-scripts-are-executable
|
|
- id: detect-private-key
|
|
- id: debug-statements
|
|
- id: name-tests-test
|
|
args: [--pytest-test-first]
|
|
- id: check-ast
|
|
- id: check-builtin-literals
|
|
- id: check-docstring-first
|
|
- id: fix-byte-order-marker
|
|
- id: mixed-line-ending
|
|
args: [--fix=lf]
|
|
- id: requirements-txt-fixer
|
|
|
|
# ===========================================================================
|
|
# BINARY BLOCKER - Prevent binary/image files from being committed
|
|
# ===========================================================================
|
|
- repo: local
|
|
hooks:
|
|
- id: no-binaries
|
|
name: Block binary/image files
|
|
entry: meta/scripts/check_no_binaries.sh
|
|
language: script
|
|
always_run: false
|
|
- id: file-length-cap
|
|
name: Enforce the 250-line file cap
|
|
# Repo-wide (--all), not per-file: a file that grows past the cap
|
|
# without being staged in this commit must still be caught. Wired only
|
|
# after the campaign that brought every file under it — turning this on
|
|
# earlier would have blocked every unrelated commit in the repo.
|
|
entry: bash meta/scripts/check_file_length.sh --all
|
|
language: system
|
|
pass_filenames: false
|
|
always_run: true
|
|
- id: directory-depth-cap
|
|
name: Enforce the directory-depth cap
|
|
# Repo-wide and ENFORCING. It ran --warn while the 46 paths under
|
|
# periodic_background/{hosts,digital_wellbeing} were over the cap;
|
|
# both units are now their own repos (kuhyx/hosts-blocker,
|
|
# kuhyx/digital-wellbeing) and the count is 0, so the cap is real.
|
|
# Re-adding --warn would silently re-open the hole it was there to
|
|
# close: put the offending path somewhere legal instead.
|
|
entry: bash meta/scripts/check_directory_depth.sh --all
|
|
language: system
|
|
pass_filenames: false
|
|
always_run: true
|
|
- id: repo-size-cap
|
|
name: Enforce the source-file ceiling
|
|
# Counts tracked files only, excluding vendored and hook-generated
|
|
# trees. Prints the count on every run so the ceiling is auditable.
|
|
entry: bash meta/scripts/check_repo_size.sh
|
|
language: system
|
|
pass_filenames: false
|
|
always_run: true
|
|
- id: ci-baseline-green
|
|
name: Refuse to build on a red CI baseline
|
|
# Checks the last COMPLETED run of each required workflow on main.
|
|
# Fails closed on a definitively red baseline; warns and passes on
|
|
# anything it cannot determine (offline, no gh, no runs yet), because
|
|
# the real per-change guarantee is the pre-push ci-mirror hook and
|
|
# blocking every commit on network reachability is not worth it.
|
|
# Bypass a deliberate fix-forward commit with CI_GREEN_SKIP=1.
|
|
entry: bash meta/scripts/check_ci_green.sh
|
|
language: system
|
|
pass_filenames: false
|
|
always_run: true
|
|
- id: ai-evidence-contract
|
|
name: Require AI evidence artifacts for code changes
|
|
entry: meta/scripts/check_ai_evidence.sh
|
|
language: script
|
|
pass_filenames: false
|
|
always_run: true
|
|
- id: ai-multifile-contract
|
|
name: Require workflow contract for multi-file code changes
|
|
entry: meta/scripts/check_agent_contract.sh
|
|
language: script
|
|
pass_filenames: false
|
|
always_run: true
|
|
- id: append-only-sessions
|
|
name: Enforce append-only session logs
|
|
entry: meta/scripts/check_append_only_sessions.sh
|
|
language: script
|
|
pass_filenames: false
|
|
always_run: true
|
|
|
|
# ===========================================================================
|
|
# POLLING SCRIPT LINTER - Detect fork-storm anti-patterns in shell scripts
|
|
# ===========================================================================
|
|
- repo: local
|
|
hooks:
|
|
- id: no-inline-python
|
|
name: Block Python logic embedded in shell scripts
|
|
entry: meta/scripts/check_no_inline_python.sh
|
|
language: script
|
|
types_or: [shell, zsh]
|
|
- id: no-polling-antipatterns
|
|
name: Block polling script anti-patterns
|
|
entry: meta/scripts/check_polling_antipatterns.sh
|
|
language: script
|
|
types: [shell]
|
|
require_serial: true
|
|
exclude: ^(\.git/|tests/)
|
|
- id: shell-coverage-ratchet
|
|
name: Every shell library has a test suite beside it
|
|
# The ratchet from meta/shell-coverage-allowlist.txt: a lib under a
|
|
# lib/ directory needs a tests/run_all.sh, unless it is allowlisted.
|
|
# Wired here on 2026-08-23. It existed but was never in pre-commit,
|
|
# so it had been silently unenforced -- a new untested lib could land
|
|
# freely. That was only affordable to fix once 578c4a6c dropped the
|
|
# jail-measured 100% bar: --all went from >600s to 0.31s, and the
|
|
# per-file mode this hook uses is milliseconds.
|
|
entry: bash meta/scripts/check_shell_coverage.sh
|
|
language: system
|
|
types: [shell]
|
|
exclude: ^third_party/
|
|
|
|
# ===========================================================================
|
|
# NOQA BLOCKER - Zero tolerance for noqa/type:ignore suppression comments
|
|
# ===========================================================================
|
|
- repo: local
|
|
hooks:
|
|
- id: no-noqa
|
|
name: Block noqa comments
|
|
entry: '(?i)#\s*(noqa|type:\s*ignore)'
|
|
language: pygrep
|
|
types: [python]
|
|
- id: no-ruff-noqa
|
|
name: Block ruff noqa file-level comments
|
|
entry: '(?i)#\s*ruff:\s*noqa'
|
|
language: pygrep
|
|
types: [python]
|
|
|
|
# ===========================================================================
|
|
# RUFF - Fast Python linter and formatter (replaces black, isort, flake8, etc.)
|
|
# ===========================================================================
|
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
rev: v0.15.2
|
|
hooks:
|
|
# Linter - run first to catch issues
|
|
- id: ruff
|
|
args:
|
|
- --fix
|
|
- --unsafe-fixes
|
|
- --exit-non-zero-on-fix
|
|
- --show-fixes
|
|
types_or: [python, pyi]
|
|
# Formatter - run after linting
|
|
- id: ruff-format
|
|
types_or: [python, pyi]
|
|
|
|
# ===========================================================================
|
|
# MYPY - Static type checking (per-commit on changed files only)
|
|
# Was on pre-push, but force-push diffs caused full-repo scans + OOM. On
|
|
# pre-commit it sees only the file(s) currently staged → near-instant.
|
|
# ===========================================================================
|
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
rev: v1.13.0
|
|
hooks:
|
|
- id: mypy
|
|
stages: [pre-commit]
|
|
args:
|
|
- --ignore-missing-imports
|
|
- --no-error-summary
|
|
- --disable-error-code=no-untyped-def
|
|
- --disable-error-code=no-untyped-call
|
|
- --disable-error-code=var-annotated
|
|
- --disable-error-code=no-any-unimported
|
|
- --disable-error-code=type-arg
|
|
- --disable-error-code=no-any-return
|
|
- --disable-error-code=misc
|
|
- --disable-error-code=unused-ignore
|
|
- --disable-error-code=unreachable
|
|
- --disable-error-code=assignment
|
|
- --disable-error-code=no-redef
|
|
- --disable-error-code=attr-defined
|
|
- --disable-error-code=arg-type
|
|
- --disable-error-code=union-attr
|
|
- --disable-error-code=call-overload
|
|
- --disable-error-code=return-value
|
|
- --disable-error-code=redundant-cast
|
|
- --disable-error-code=empty-body
|
|
- --disable-error-code=list-item
|
|
exclude: >-
|
|
(?x)^(
|
|
Bash/.*|
|
|
\.venv/.*|
|
|
linux_configuration/misc/tools/.*
|
|
)$
|
|
additional_dependencies:
|
|
- types-requests
|
|
- types-PyYAML
|
|
- types-python-dateutil
|
|
|
|
# ===========================================================================
|
|
# PYLINT - Comprehensive Python linter (per-commit on changed files only)
|
|
# Was on pre-push, but force-push diffs caused full-repo scans + OOM.
|
|
# ===========================================================================
|
|
- repo: https://github.com/pylint-dev/pylint
|
|
rev: v3.3.2
|
|
hooks:
|
|
- id: pylint
|
|
stages: [pre-commit]
|
|
args:
|
|
- --rcfile=pyproject.toml
|
|
- --fail-under=10
|
|
- --jobs=4
|
|
additional_dependencies:
|
|
- pytest
|
|
- python-chess
|
|
- requests
|
|
- pygame
|
|
- pillow
|
|
# archwiki_rag parses the local arch-wiki-docs HTML dump. pylint runs
|
|
# in its own venv, so a package being in meta/requirements.txt is not
|
|
# enough for it to resolve the import.
|
|
- beautifulsoup4
|
|
- markdownify
|
|
# android_ui parses `uiautomator dump` output. Same reason as
|
|
# beautifulsoup4 above: requirements.txt is not on pylint's path.
|
|
- defusedxml
|
|
# artgate computes image gates over pixel arrays. Same reason again:
|
|
# it is the first package here to import numpy.
|
|
- numpy
|
|
- gatelock @ git+https://github.com/kuhyx/utils@gatelock-v0.1.0#subdirectory=gatelock
|
|
- anthropic
|
|
- rich
|
|
- typer
|
|
# Test suites and conftest fixtures are linted separately; they use
|
|
# patterns (protected-access, missing docstrings, fixture shadowing)
|
|
# that don't belong in the source-code 10/10 gate.
|
|
exclude: ^(Bash/|\.venv/)|(^|/)(tests/|conftest\.py)
|
|
|
|
# ===========================================================================
|
|
# BANDIT - Security linter (per-commit on changed files only)
|
|
# Was on pre-push, but force-push diffs caused full-repo scans + OOM.
|
|
# ===========================================================================
|
|
- repo: https://github.com/PyCQA/bandit
|
|
rev: 1.7.10
|
|
hooks:
|
|
- id: bandit
|
|
stages: [pre-commit]
|
|
args:
|
|
- -c
|
|
- pyproject.toml
|
|
- --severity-level=high
|
|
- --confidence-level=medium
|
|
- --skip=B113
|
|
additional_dependencies: ["bandit[toml]"]
|
|
exclude: ^(Bash/|\.venv/|tests/|.*test.*\.py$)
|
|
|
|
# ===========================================================================
|
|
# PYTEST + COVERAGE - Run tests and enforce 100% code coverage
|
|
# Only tests for subpackages with changed files are run (see script).
|
|
# Uses pytest-xdist (-n auto) to parallelize across all CPUs.
|
|
# ===========================================================================
|
|
- repo: local
|
|
hooks:
|
|
- id: pytest-coverage
|
|
name: pytest with coverage enforcement
|
|
# Serialised against builds and pacman transactions on this 7.6 GB
|
|
# machine via the heavy-job lock. run_with_heavy_lock.sh is a plain
|
|
# passthrough on any clone that has not installed one.
|
|
entry: bash meta/scripts/run_with_heavy_lock.sh pytest python meta/scripts/pytest_changed_packages.py
|
|
language: system
|
|
types: [python]
|
|
pass_filenames: true
|
|
require_serial: true
|
|
stages: [pre-commit]
|
|
- id: requirements-sync
|
|
name: requirements.txt covers all python_pkg imports
|
|
entry: python3 meta/scripts/check_requirements_sync.py --package python_pkg
|
|
language: system
|
|
pass_filenames: false
|
|
files: ^(python_pkg/.*\.py|requirements\.txt)$
|
|
- id: requirements-test-sync
|
|
name: requirements-test.txt covers all python_pkg imports
|
|
# python-tests.yml installs this SUBSET rather than the full list, so
|
|
# it needs the same completeness guarantee. Without this hook a new
|
|
# third-party import would pass locally and fail in CI with a bare
|
|
# ModuleNotFoundError.
|
|
entry: python3 meta/scripts/check_requirements_sync.py --package python_pkg --requirements meta/requirements-test.txt
|
|
language: system
|
|
pass_filenames: false
|
|
files: ^(python_pkg/.*\.py|meta/requirements-test\.txt)$
|
|
- id: session-autopsy-hook-mutations
|
|
name: session_autopsy hook tests are non-vacuous (mutation)
|
|
entry: python3 meta/scripts/mutate_session_autopsy_hooks.py
|
|
language: system
|
|
pass_filenames: false
|
|
require_serial: true
|
|
# Scoped to the two files that can invalidate the proof: the suite
|
|
# itself and the mutation definitions. Takes ~40s, so it must not run
|
|
# on unrelated commits. Skips itself where ~/.claude is absent (CI).
|
|
files: ^(linux_configuration/tests/test_session_autopsy_hooks\.py|meta/scripts/mutate_session_autopsy_hooks\.py)$
|
|
- id: ci-mirror
|
|
name: CI mirror (clean-venv install + --all-files + changed-pkg pytest)
|
|
entry: bash meta/scripts/ci_mirror.sh
|
|
language: system
|
|
pass_filenames: false
|
|
always_run: true
|
|
require_serial: true
|
|
stages: [pre-push]
|
|
|
|
# ===========================================================================
|
|
# VULTURE - Dead code detection (disabled - doesn't work well with pre-commit)
|
|
# ===========================================================================
|
|
# - repo: https://github.com/jendrikseipp/vulture
|
|
# rev: v2.13
|
|
# hooks:
|
|
# - id: vulture
|
|
# args:
|
|
# - --min-confidence=80
|
|
# - --exclude=.venv,Bash,__pycache__
|
|
# exclude: ^(Bash/|\.venv/)
|
|
|
|
# ===========================================================================
|
|
# PYUPGRADE - Upgrade Python syntax (disabled - incompatible with Python 3.14)
|
|
# ===========================================================================
|
|
# - repo: https://github.com/asottile/pyupgrade
|
|
# rev: v3.19.0
|
|
# hooks:
|
|
# - id: pyupgrade
|
|
# args:
|
|
# - --py310-plus
|
|
|
|
# ===========================================================================
|
|
# CODESPELL - Spell checking in code (expanded ignore list for non-English)
|
|
# ===========================================================================
|
|
- repo: https://github.com/codespell-project/codespell
|
|
rev: v2.3.0
|
|
hooks:
|
|
- id: codespell
|
|
args:
|
|
- --skip=*.json,*.lock,*-lock.yaml,*.min.js,*.min.css,.git,__pycache__,.venv,*.txt
|
|
# Many entries below are Polish words, not typos: they are field
|
|
# names from Polish data formats (e.g. `dokument` in the e-paragon /
|
|
# JPK e-receipt schema that billsplit parses). "Correcting" them to
|
|
# English breaks the parsers that match on them.
|
|
# `daa` is MediaTek's Download Agent Authentication, a BROM security
|
|
# feature named in the mtk_root notes - not a misspelling of "data".
|
|
# `artic` is SearXNG's engine id for the Art Institute of Chicago
|
|
# (setup_searxng.sh), not a misspelling of "arctic" - renaming it
|
|
# would stop matching the engine.
|
|
- --ignore-words-list=als,ans,ect,nd,som,sur,te,nam,numer,lew,sie,wil,postion,clen,ther,folow,derrive,ony,tje,noe,theses,crate,doubleclick,wile,tabel,pary,blok,bloc,proces,serwer,parametr,adres,hart,dout,metod,tekst,synonim,grup,mosty,lokal,skalar,milion,nowe,tre,hel,alph,iif,dokument,daa,artic
|
|
exclude: ^(Bash/ffmpeg-build/|LaTeX/|.*\.geojson$)
|
|
|
|
# ===========================================================================
|
|
# DOCFORMATTER - Format docstrings (disabled - causes recursion errors)
|
|
# ===========================================================================
|
|
# - repo: local
|
|
# hooks:
|
|
# - id: docformatter
|
|
# name: docformatter
|
|
# entry: docformatter
|
|
# language: system
|
|
# types: [python]
|
|
# args:
|
|
# - --in-place
|
|
# - --wrap-summaries=88
|
|
# - --wrap-descriptions=88
|
|
|
|
# ===========================================================================
|
|
# INTERROGATE - Docstring coverage (disabled - causes recursion on large files)
|
|
# ===========================================================================
|
|
# - repo: https://github.com/econchick/interrogate
|
|
# rev: 1.7.0
|
|
# hooks:
|
|
# - id: interrogate
|
|
# args:
|
|
# - --fail-under=0
|
|
# - --verbose
|
|
# - --ignore-init-method
|
|
# - --ignore-init-module
|
|
# - --ignore-magic
|
|
# - --ignore-private
|
|
# - --ignore-semiprivate
|
|
# - --exclude=Bash,.venv,__pycache__
|
|
# pass_filenames: false
|
|
|
|
# ===========================================================================
|
|
# AUTOFLAKE - Remove unused imports/variables
|
|
# Disabled: fully redundant with ruff (F401, F841, F811) + --fix
|
|
# ===========================================================================
|
|
# - repo: https://github.com/PyCQA/autoflake
|
|
# rev: v2.3.1
|
|
# hooks:
|
|
# - id: autoflake
|
|
# args:
|
|
# - --in-place
|
|
# - --remove-all-unused-imports
|
|
# - --remove-unused-variables
|
|
# - --remove-duplicate-keys
|
|
# - --expand-star-imports
|
|
|
|
# ===========================================================================
|
|
# SAFETY - Check for security vulnerabilities in dependencies
|
|
# ===========================================================================
|
|
# Note: Safety requires API key for full functionality, disabled by default
|
|
# - repo: https://github.com/Lucas-C/pre-commit-hooks-safety
|
|
# rev: v1.3.2
|
|
# hooks:
|
|
# - id: python-safety-dependencies-check
|
|
# files: requirements.*\.txt$
|
|
|
|
# ===========================================================================
|
|
# PYRIGHT - Microsoft's type checker (very strict, optional)
|
|
# ===========================================================================
|
|
# Uncomment to enable - can be slow and very strict
|
|
# - repo: https://github.com/RobertCraiworthy/pyright-action
|
|
# rev: v1.1.350
|
|
# hooks:
|
|
# - id: pyright
|
|
|
|
# ===========================================================================
|
|
# CHECK JSON/YAML/TOML formatting (runs on push only — slow Node.js startup)
|
|
# ===========================================================================
|
|
- repo: local
|
|
hooks:
|
|
- id: prettier
|
|
name: prettier (capped scope)
|
|
# Wrapper runs prettier inside its own systemd-run scope so its
|
|
# memory budget is independent of the outer pre-push cgroup that
|
|
# has already accumulated page cache from pytest/mypy/pylint.
|
|
entry: meta/scripts/run_prettier_capped.sh
|
|
language: system
|
|
types_or: [yaml, json, markdown]
|
|
exclude: >-
|
|
(?x)^(
|
|
Bash/.*|
|
|
\.venv/.*|
|
|
third_party/.*|
|
|
\.github/skills/.*|
|
|
docs/superpowers/(plans|specs)/.*|
|
|
linux_configuration/report/.*|
|
|
.*\.lock
|
|
)$
|
|
stages: [pre-push]
|
|
|
|
# ===========================================================================
|
|
# SHELLCHECK - Shell script linting
|
|
# Wrapper batches files to avoid OOM on large repos.
|
|
# ===========================================================================
|
|
- repo: local
|
|
hooks:
|
|
- id: shellcheck
|
|
name: shellcheck
|
|
# NO --severity filter: every finding shellcheck reports, down to info
|
|
# and style, fails the commit. The previous --severity=warning quietly
|
|
# accepted 222 findings across 94 of 244 shell files -- and among them
|
|
# were real defects, not noise: two scripts that reported SUCCESS on an
|
|
# unknown command, five that sourced a path off by one directory (so
|
|
# they failed at runtime), a stale `source=` directive that had silently
|
|
# disabled following for six i3blocks scripts, and a diagnostic that
|
|
# would hang on stdin when its file list came back empty.
|
|
# Settings live in .shellcheckrc (external-sources, source-path).
|
|
entry: bash -c 'printf "%s\0" "$@" | xargs -0 -n 40 shellcheck' --
|
|
language: system
|
|
types: [shell]
|
|
# shellcheck only understands sh/bash/dash/ksh; it cannot parse zsh
|
|
# syntax (e.g. extended globs like (#s)). zsh files are checked by the
|
|
# zsh-syntax hook below instead.
|
|
exclude_types: [zsh]
|
|
# Vendored upstream code: we do not own it and patches here would be
|
|
# lost on the next vendor sync. Matches the prettier hook's exclusion.
|
|
#
|
|
# PKGBUILDs are makepkg manifests, not standalone scripts: they have no
|
|
# shebang by design, and pkgname/pkgver/source/sha512sums are read by
|
|
# makepkg while pkgdir/srcdir are injected by it. shellcheck therefore
|
|
# reports every one of them as unused-or-undefined (SC2148/SC2034/
|
|
# SC2154) -- all false positives, and none suppressible without
|
|
# littering the file with directives. Same reasoning as zsh above:
|
|
# the dialect is outside what shellcheck can judge.
|
|
exclude: ^third_party/|(^|/)PKGBUILD$
|
|
|
|
# ===========================================================================
|
|
# ZSH SYNTAX - zsh -n parse check (shellcheck has no zsh mode)
|
|
# ===========================================================================
|
|
- repo: local
|
|
hooks:
|
|
- id: zsh-syntax
|
|
name: zsh syntax check
|
|
entry: bash -c 'for f in "$@"; do zsh -n "$f" || exit 1; done' --
|
|
language: system
|
|
types: [zsh]
|
|
|
|
# ===========================================================================
|
|
# CHECK PYTHON LOCATION - All Python files must be under python_pkg/
|
|
# ===========================================================================
|
|
- repo: local
|
|
hooks:
|
|
- id: check-python-location
|
|
name: check Python files are under python_pkg/
|
|
entry: meta/scripts/check_python_location.sh
|
|
language: script
|
|
types: [python]
|
|
|
|
# ===========================================================================
|
|
# REMOVE EMPTY DIRECTORIES - Clean up empty folders in the repo
|
|
# ===========================================================================
|
|
- repo: local
|
|
hooks:
|
|
- id: remove-empty-dirs
|
|
name: remove empty directories
|
|
entry: find . -type d -empty -not -path './.git/*' -delete -print
|
|
language: system
|
|
pass_filenames: false
|
|
always_run: true
|
|
|
|
# ===========================================================================
|
|
# SECRET PATTERNS - Block commits containing sensitive data
|
|
# ===========================================================================
|
|
- repo: local
|
|
hooks:
|
|
- id: check-no-secrets
|
|
name: check for leaked secrets
|
|
entry: meta/scripts/check_no_secrets.sh
|
|
language: script
|
|
exclude: ^(\.secret-patterns|\.pre-commit-config\.yaml|.*\.geojson)$
|
|
|
|
- id: check-no-dufs-conf
|
|
name: block dufs secret config (.dufs_cloud.conf)
|
|
entry: meta/scripts/check_no_dufs_conf.sh
|
|
language: script
|
|
always_run: true
|
|
pass_filenames: false
|
|
|
|
# ===========================================================================
|
|
# COMMITIZEN - Conventional commits (optional)
|
|
# ===========================================================================
|
|
# - repo: https://github.com/commitizen-tools/commitizen
|
|
# rev: v3.13.0
|
|
# hooks:
|
|
# - id: commitizen
|
|
# - id: commitizen-branch
|
|
# stages: [push]
|
|
|
|
# Four markdown namespaces (README / CLAUDE* / DOCS* / TODO*), plus the
|
|
# rule that a TODO carries "REMOVE ME AFTER FINISH" and nothing else may.
|
|
# Shared gate in ~/src/utils owns the namespaces and the exemption list, so
|
|
# one repo's idea of a valid name cannot drift from every other repo's.
|
|
- id: md-naming
|
|
name: markdown naming convention
|
|
entry: scripts/check_md_naming.sh
|
|
language: system
|
|
files: \.(md|markdown)$
|
|
|
|
# Every dependency on its ecosystem's newest STABLE release, exact-pinned
|
|
# so the question is mechanically answerable at all.
|
|
#
|
|
# `files:` is what keeps this cheap: a commit touching only source makes
|
|
# ZERO network requests, and manifest commits mostly hit a 6h disk cache.
|
|
#
|
|
# Runs WITHOUT --strict on purpose. Offline it degrades to the cached
|
|
# answer and passes with a loud banner; `--no-verify` is banned here, so
|
|
# a hook that hard-failed on a flaky connection would leave no way to
|
|
# commit at all. CI, always online, is the strict authority.
|
|
- id: dependency-freshness
|
|
name: dependencies on newest stable
|
|
entry: scripts/check_dependency_freshness.sh
|
|
language: system
|
|
pass_filenames: true
|
|
files: >-
|
|
(pubspec\.(yaml|lock)|pyproject\.toml|requirements.*\.txt|uv\.lock
|
|
|package\.json|package-lock\.json|pnpm-lock\.yaml
|
|
|Cargo\.(toml|lock)|go\.(mod|sum)
|
|
|\.fvmrc|\.nvmrc|\.python-version
|
|
|\.github/workflows/.*\.ya?ml)$
|