#!/usr/bin/env bash # ────────────────────────────────────────────────────────────────── # CxIDE — commit-msg hook # Enforces conventional commit message format. # Install: cp hooks/commit-msg .git/hooks/commit-msg # ────────────────────────────────────────────────────────────────── set -euo pipefail COMMIT_MSG_FILE="$1" MSG="$(head -1 "$COMMIT_MSG_FILE")" RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[0;33m'; RESET='\033[0m' # ─── Conventional Commits format ───────────────────────────────── # type(scope): description # Types: feat, fix, refactor, docs, test, build, ci, chore, perf, style, agent PATTERN='^(feat|fix|refactor|docs|test|build|ci|chore|perf|style|agent)(\([a-z0-9-]+\))?: .{3,72}$' if ! echo "$MSG" | grep -qE "$PATTERN"; then echo "" printf "${RED}✗ Invalid commit message format${RESET}\n" echo "" echo " Expected: type(scope): description" echo "" echo " Types: feat, fix, refactor, docs, test, build, ci, chore, perf, style, agent" echo " Scopes: core, agent, views, models, services, vm, engine, tools (optional)" echo "" echo " Examples:" echo " feat(agent): add code review tool" echo " fix(core): correct cyclomatic complexity for switch" echo " docs: update build instructions" echo " refactor(views): split sidebar into components" echo "" printf " Your message: ${YELLOW}%s${RESET}\n" "$MSG" echo "" exit 1 fi # ─── Reject WIP on main/master ────────────────────────────────── BRANCH="$(git symbolic-ref --short HEAD 2>/dev/null || echo '')" if [[ "$BRANCH" == "main" || "$BRANCH" == "master" ]]; then if echo "$MSG" | grep -qiE '^(wip|fixup|squash)'; then printf "${RED}✗ WIP/fixup/squash commits not allowed on %s${RESET}\n" "$BRANCH" exit 1 fi fi printf "${GREEN}✓${RESET} Commit message OK\n"