diff --git a/CLAUDE.md b/CLAUDE.md index 184b026..1f76fff 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -117,7 +117,7 @@ Kurzbefehl für den gesamten Ablauf: `/story` | Event | Trigger | Skript | Aktion | |---|---|---|---| -| `PreToolUse` | Bash | `hooks/pre-bash-checks.sh` | Git-main-Schutz, apt -y Blockade | +| `PreToolUse` | Bash | `hooks/pre-bash-checks.sh` | Git-main-Schutz, Commit-Message-Validierung (Conventional Commits), apt -y Blockade | | `PostToolUse` | Edit / Write | `hooks/auto-format.sh` | `ruff` (Python), `eslint --fix` (JS/TS/Vue) oder `shellcheck` (Bash) | | `Stop` | Session-Ende | `hooks/verify-on-stop.sh` | Uncommittete Änderungen anzeigen | diff --git a/dotfiles/CLAUDE.md b/dotfiles/CLAUDE.md index 0e3a000..74ae8f8 100644 --- a/dotfiles/CLAUDE.md +++ b/dotfiles/CLAUDE.md @@ -41,6 +41,10 @@ PRs muessen jedes Akzeptanzkriterium einzeln als Checkbox auflisten und bestaeti Niemals direkt auf `main` committen. Alle Aenderungen ueber Feature-Branches und PRs. - **Kleinteilige Commits:** Pro Commit nur ein einziges Thema. Nur die zum Thema gehörenden Dateien committen — keine thematisch gemischten Commits. +- **Commit-Messages:** Conventional Commits, deutsche Beschreibung + - Subject: `: ` — max 72 Zeichen, kein Punkt am Ende + - Typen: `feat`, `fix`, `docs`, `refactor`, `test`, `chore`, `perf`, `ci`, `build`, `style` + - Body optional, durch Leerzeile getrennt — erklaert das Warum, nicht das Was ## Fehlende Tools diff --git a/hooks/pre-bash-checks.sh b/hooks/pre-bash-checks.sh index f7f4866..9d94e21 100755 --- a/hooks/pre-bash-checks.sh +++ b/hooks/pre-bash-checks.sh @@ -3,13 +3,47 @@ set -euo pipefail cmd=$(jq -r '.tool_input.command // ""') -# Git-Branch-Schutz: kein direkter Commit auf main +VALID_TYPES="feat|fix|docs|refactor|test|chore|perf|ci|build|style" + +extract_subject() { + local cmd="$1" + if echo "$cmd" | grep -qE "cat\s+<<"; then + echo "$cmd" | sed -n "/cat </dev/null || echo "") if [ "$branch" = "main" ]; then printf '{"continue":false,"stopReason":"BLOCKIERT: Direkter Commit auf main verboten (globale Regel). Bitte zuerst Feature-Branch erstellen: git checkout -b session/YYYY-MM-DD-titel"}\n' exit 0 fi + + # Commit-Message: Conventional Commits Format pruefen + subject=$(extract_subject "$cmd") + + if [ -n "$subject" ]; then + if ! echo "$subject" | grep -qP "^(${VALID_TYPES})(\\(.+\\))?\\!?:\\s.+"; then + printf '{"continue":false,"stopReason":"BLOCKIERT: Commit-Message folgt nicht dem Conventional-Commits-Format. Erwartet: : . Erlaubte Typen: feat, fix, docs, refactor, test, chore, perf, ci, build, style"}\n' + exit 0 + fi + + if [ ${#subject} -gt 72 ]; then + printf '{"continue":false,"stopReason":"BLOCKIERT: Commit-Message Subject zu lang (%d Zeichen, max 72)."}\n' "${#subject}" + exit 0 + fi + + if echo "$subject" | grep -qP '\.\s*$'; then + printf '{"continue":false,"stopReason":"BLOCKIERT: Commit-Message Subject darf nicht mit einem Punkt enden."}\n' + exit 0 + fi + fi fi # apt -y verboten