#!/bin/sh # Pre-commit: same checks as CI. Fix here, not in CI. set -e echo "🔍 Pre-commit checks..." # Lint + types (only if TS files staged) STAGED_TS=$(git diff --cached --name-only | grep -E '\.(ts|tsx)$' || true) if [ -n "$STAGED_TS" ]; then echo " → lint + tsc..." pnpm lint --quiet npx tsc --noEmit fi # Unit tests echo " → tests..." pnpm test --run --silent echo "✅ Pre-commit passed" # ── CodeScene Code Health gate ──────────────────────────────────────────── # Blocks commit if Hotspot < 9.5 OR Average < 9.0. # Note: remote scores lag behind local changes (update after push + re-analysis). # This catches regressions from previous pushes and notifies Claude Code immediately. # If `pre_commit_code_health_safeguard` fails: extract hooks, split components, # reduce complexity. Never use eslint-disable, #[allow(...)], or `as any`. echo "🏥 CodeScene code health check..." if [ -z "$CODESCENE_PAT" ] || [ -z "$CODESCENE_PROJECT_ID" ]; then echo " ⚠️ CODESCENE_PAT or CODESCENE_PROJECT_ID not set — skipping (CI will enforce)" else API_RESPONSE=$(curl -sf \ -H "Authorization: Bearer $CODESCENE_PAT" \ -H "Accept: application/json" \ "https://api.codescene.io/v2/projects/$CODESCENE_PROJECT_ID" 2>/dev/null || echo "{}") HOTSPOT_SCORE=$(echo "$API_RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['analysis']['hotspot_code_health']['now'])" 2>/dev/null || echo "") AVERAGE_SCORE=$(echo "$API_RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['analysis']['code_health']['now'])" 2>/dev/null || echo "") if [ -z "$HOTSPOT_SCORE" ] || [ -z "$AVERAGE_SCORE" ]; then echo " ⚠️ Could not fetch CodeScene scores — skipping (CI will enforce)" else echo " Hotspot Code Health: $HOTSPOT_SCORE (threshold: 9.5)" echo " Average Code Health: $AVERAGE_SCORE (threshold: 8.9)" python3 -c " import sys hotspot = float('$HOTSPOT_SCORE') average = float('$AVERAGE_SCORE') failed = False if hotspot < 9.5: print(f'FAIL: Hotspot Code Health {hotspot:.2f} < 9.5 — extract hooks, split components, reduce complexity') failed = True else: print(f'OK: Hotspot {hotspot:.2f} >= 9.5') if average < 8.9: print(f'FAIL: Average Code Health {average:.2f} < 9.0 — recent changes introduced regressions in non-hotspot files') print(' Review files changed in this task. Never use eslint-disable, #[allow(...)], or as any to bypass.') failed = True else: print(f'OK: Average {average:.2f} >= 9.0') if failed: sys.exit(1) " || exit 1 fi fi