- Both hotspot (≥9.5) and average (≥8.9) gates now block commit/push/CI - Current average: 8.97 — threshold set at 8.9 to block regressions without blocking the current state; aspirational target remains 9.5 - pre-commit: replaced phantom pre_commit_code_health_safeguard with real inline check - pre-push: CodeScene step is now blocking (was informational-only) - CLAUDE.md: explicit instructions to monitor both scores via MCP CodeScene
62 lines
2.6 KiB
Bash
Executable File
62 lines
2.6 KiB
Bash
Executable File
#!/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
|