autoworkflow 1.2.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,324 @@
1
+ #!/bin/bash
2
+ # autoworkflow.sh
3
+ # AutoWorkflow CLI Orchestrator
4
+ # Usage: ./scripts/autoworkflow.sh [command] [options]
5
+
6
+ set -o pipefail
7
+
8
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9
+ PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
10
+
11
+ # Colors
12
+ RED='\033[0;31m'
13
+ GREEN='\033[0;32m'
14
+ YELLOW='\033[1;33m'
15
+ BLUE='\033[0;34m'
16
+ CYAN='\033[0;36m'
17
+ NC='\033[0m'
18
+
19
+ # Configuration
20
+ MAX_FIX_ATTEMPTS=10
21
+
22
+ cd "$PROJECT_ROOT"
23
+
24
+ print_header() {
25
+ echo ""
26
+ echo -e "${CYAN}╔══════════════════════════════════════════════════════════════╗${NC}"
27
+ echo -e "${CYAN}║ AUTOWORKFLOW SYSTEM ║${NC}"
28
+ echo -e "${CYAN}╚══════════════════════════════════════════════════════════════╝${NC}"
29
+ echo ""
30
+ }
31
+
32
+ print_phase() {
33
+ local phase="$1"
34
+ echo ""
35
+ echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
36
+ echo -e "${BLUE} PHASE: $phase${NC}"
37
+ echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
38
+ echo ""
39
+ }
40
+
41
+ # ─────────────────────────────────────────────────────────────
42
+ # VERIFICATION
43
+ # ─────────────────────────────────────────────────────────────
44
+
45
+ run_verification() {
46
+ print_phase "VERIFICATION"
47
+
48
+ local has_errors=0
49
+
50
+ # TypeScript check
51
+ echo "📋 Running TypeScript check..."
52
+ if npm run typecheck 2>&1; then
53
+ echo -e "${GREEN}✓ TypeScript: No errors${NC}"
54
+ else
55
+ echo -e "${RED}✗ TypeScript: Errors found${NC}"
56
+ has_errors=1
57
+ fi
58
+
59
+ echo ""
60
+
61
+ # ESLint check
62
+ echo "📋 Running ESLint check..."
63
+ if npm run lint 2>&1; then
64
+ echo -e "${GREEN}✓ ESLint: No warnings${NC}"
65
+ else
66
+ echo -e "${RED}✗ ESLint: Warnings/errors found${NC}"
67
+ has_errors=1
68
+ fi
69
+
70
+ echo ""
71
+
72
+ if [ $has_errors -eq 0 ]; then
73
+ echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
74
+ echo -e "${GREEN}✅ VERIFICATION PASSED${NC}"
75
+ echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
76
+ return 0
77
+ else
78
+ echo -e "${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
79
+ echo -e "${RED}❌ VERIFICATION FAILED${NC}"
80
+ echo -e "${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
81
+ return 1
82
+ fi
83
+ }
84
+
85
+ # ─────────────────────────────────────────────────────────────
86
+ # AUDIT
87
+ # ─────────────────────────────────────────────────────────────
88
+
89
+ run_audit() {
90
+ print_phase "AUDIT"
91
+
92
+ local has_issues=0
93
+
94
+ # UI Enforcement check
95
+ echo "🔍 Running UI enforcement check..."
96
+ if [ -f "./scripts/check-ui-enforcement.sh" ]; then
97
+ if ./scripts/check-ui-enforcement.sh 2>&1; then
98
+ echo -e "${GREEN}✓ UI Enforcement: No orphan features${NC}"
99
+ else
100
+ echo -e "${RED}✗ UI Enforcement: Orphan features found${NC}"
101
+ has_issues=1
102
+ fi
103
+ else
104
+ echo -e "${YELLOW}⚠ UI Enforcement: Script not found, skipping${NC}"
105
+ fi
106
+
107
+ echo ""
108
+
109
+ # Circular dependency check
110
+ echo "🔍 Running circular dependency check..."
111
+ if command -v npx &> /dev/null && [ -d "src" ]; then
112
+ CYCLES=$(npx madge --circular --extensions ts,tsx src/ 2>/dev/null)
113
+ if [ -z "$CYCLES" ] || [[ "$CYCLES" == *"No circular"* ]]; then
114
+ echo -e "${GREEN}✓ Circular Deps: No cycles detected${NC}"
115
+ else
116
+ echo -e "${RED}✗ Circular Deps: Cycles found${NC}"
117
+ echo "$CYCLES"
118
+ has_issues=1
119
+ fi
120
+ else
121
+ echo -e "${YELLOW}⚠ Circular Deps: madge not available or no src/, skipping${NC}"
122
+ fi
123
+
124
+ echo ""
125
+
126
+ if [ $has_issues -eq 0 ]; then
127
+ echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
128
+ echo -e "${GREEN}✅ AUDIT PASSED${NC}"
129
+ echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
130
+ return 0
131
+ else
132
+ echo -e "${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
133
+ echo -e "${RED}❌ AUDIT FAILED${NC}"
134
+ echo -e "${RED}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
135
+ return 1
136
+ fi
137
+ }
138
+
139
+ # ─────────────────────────────────────────────────────────────
140
+ # PRE-COMMIT CHECK
141
+ # ─────────────────────────────────────────────────────────────
142
+
143
+ run_precommit_check() {
144
+ print_phase "PRE-COMMIT CHECK"
145
+
146
+ local has_issues=0
147
+
148
+ # Check for TODO/FIXME
149
+ echo "🔍 Checking for TODO/FIXME comments..."
150
+ if git diff --cached --name-only 2>/dev/null | xargs grep -l "TODO\|FIXME\|XXX\|HACK" 2>/dev/null; then
151
+ echo -e "${RED}✗ Found TODO/FIXME comments in staged files${NC}"
152
+ has_issues=1
153
+ else
154
+ echo -e "${GREEN}✓ No TODO/FIXME comments${NC}"
155
+ fi
156
+
157
+ # Check for console.log
158
+ echo "🔍 Checking for console.log statements..."
159
+ if git diff --cached --name-only 2>/dev/null | xargs grep -l "console\.\(log\|debug\|info\)" 2>/dev/null; then
160
+ echo -e "${RED}✗ Found console.log statements in staged files${NC}"
161
+ has_issues=1
162
+ else
163
+ echo -e "${GREEN}✓ No console.log statements${NC}"
164
+ fi
165
+
166
+ echo ""
167
+
168
+ if [ $has_issues -eq 0 ]; then
169
+ echo -e "${GREEN}✓ Pre-commit checks passed${NC}"
170
+ return 0
171
+ else
172
+ echo -e "${RED}✗ Pre-commit checks failed${NC}"
173
+ return 1
174
+ fi
175
+ }
176
+
177
+ # ─────────────────────────────────────────────────────────────
178
+ # COMMIT
179
+ # ─────────────────────────────────────────────────────────────
180
+
181
+ run_commit() {
182
+ local msg="${1:-"chore: update"}"
183
+
184
+ print_phase "COMMIT"
185
+
186
+ # Check for changes
187
+ if git diff --quiet && git diff --staged --quiet; then
188
+ echo -e "${YELLOW}⚠️ No changes to commit${NC}"
189
+ return 0
190
+ fi
191
+
192
+ # Run verification first
193
+ if ! run_verification; then
194
+ echo -e "${RED}❌ Cannot commit: verification failed${NC}"
195
+ return 1
196
+ fi
197
+
198
+ # Run pre-commit checks
199
+ if ! run_precommit_check; then
200
+ echo -e "${RED}❌ Cannot commit: pre-commit checks failed${NC}"
201
+ return 1
202
+ fi
203
+
204
+ # Stage and commit
205
+ echo ""
206
+ echo "📝 Staging changes..."
207
+ git add -A
208
+
209
+ echo ""
210
+ echo "Files to be committed:"
211
+ git diff --staged --name-only | head -20
212
+
213
+ echo ""
214
+ echo "💾 Committing..."
215
+ git commit -m "$msg"
216
+
217
+ COMMIT_HASH=$(git rev-parse --short HEAD)
218
+
219
+ echo ""
220
+ echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
221
+ echo -e "${GREEN}✅ COMMIT SUCCESSFUL: $COMMIT_HASH${NC}"
222
+ echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
223
+
224
+ return 0
225
+ }
226
+
227
+ # ─────────────────────────────────────────────────────────────
228
+ # FULL WORKFLOW
229
+ # ─────────────────────────────────────────────────────────────
230
+
231
+ run_full_workflow() {
232
+ local commit_msg="${1:-"feat: implement feature"}"
233
+
234
+ print_header
235
+
236
+ echo "Starting full workflow..."
237
+ echo "Commit message: $commit_msg"
238
+
239
+ # Step 1: Verify
240
+ if ! run_verification; then
241
+ echo ""
242
+ echo -e "${YELLOW}⚠️ Verification failed. Fix errors and try again.${NC}"
243
+ return 1
244
+ fi
245
+
246
+ # Step 2: Audit
247
+ if ! run_audit; then
248
+ echo ""
249
+ echo -e "${YELLOW}⚠️ Audit failed. Fix issues and try again.${NC}"
250
+ return 1
251
+ fi
252
+
253
+ # Step 3: Commit
254
+ run_commit "$commit_msg"
255
+
256
+ echo ""
257
+ echo -e "${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}"
258
+ echo -e "${GREEN}║ WORKFLOW COMPLETE ║${NC}"
259
+ echo -e "${GREEN}╚══════════════════════════════════════════════════════════════╝${NC}"
260
+ echo ""
261
+ }
262
+
263
+ # ─────────────────────────────────────────────────────────────
264
+ # STATUS
265
+ # ─────────────────────────────────────────────────────────────
266
+
267
+ show_status() {
268
+ print_header
269
+ print_phase "STATUS"
270
+
271
+ echo "📁 Git Status:"
272
+ git status --short 2>/dev/null || echo " Not a git repository"
273
+ echo ""
274
+
275
+ echo "📜 Recent Commits:"
276
+ git log --oneline -5 2>/dev/null || echo " No commits yet"
277
+ echo ""
278
+
279
+ echo "🔍 Verification Status:"
280
+ run_verification || true
281
+ }
282
+
283
+ # ─────────────────────────────────────────────────────────────
284
+ # MAIN
285
+ # ─────────────────────────────────────────────────────────────
286
+
287
+ case "${1:-help}" in
288
+ verify)
289
+ print_header
290
+ run_verification
291
+ ;;
292
+ audit)
293
+ print_header
294
+ run_audit
295
+ ;;
296
+ commit)
297
+ run_commit "${2:-"chore: update"}"
298
+ ;;
299
+ full)
300
+ run_full_workflow "${2:-"feat: implement feature"}"
301
+ ;;
302
+ status)
303
+ show_status
304
+ ;;
305
+ help|*)
306
+ echo "AutoWorkflow CLI"
307
+ echo ""
308
+ echo "Usage: $0 <command> [options]"
309
+ echo ""
310
+ echo "Commands:"
311
+ echo " status Show current status"
312
+ echo " verify Run TypeScript + ESLint verification"
313
+ echo " audit Run UI enforcement + circular deps check"
314
+ echo " commit \"msg\" Verify and commit with message"
315
+ echo " full \"msg\" Full workflow (verify → audit → commit)"
316
+ echo ""
317
+ echo "Examples:"
318
+ echo " $0 status"
319
+ echo " $0 verify"
320
+ echo " $0 commit \"feat: add login page\""
321
+ echo " $0 full \"feat: add user profile\""
322
+ echo ""
323
+ ;;
324
+ esac
@@ -0,0 +1,177 @@
1
+ #!/bin/bash
2
+ # check-ui-enforcement.sh
3
+ # Checks for orphan features (backend without UI)
4
+ # This enforces the "No Orphan Features" rule
5
+
6
+ set -o pipefail
7
+
8
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9
+ PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
10
+
11
+ # Colors
12
+ RED='\033[0;31m'
13
+ GREEN='\033[0;32m'
14
+ YELLOW='\033[1;33m'
15
+ CYAN='\033[0;36m'
16
+ NC='\033[0m'
17
+
18
+ cd "$PROJECT_ROOT"
19
+
20
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
21
+ echo "🔍 UI ENFORCEMENT CHECK"
22
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
23
+ echo ""
24
+
25
+ ORPHANS_FOUND=0
26
+ WARNINGS=""
27
+
28
+ # ─────────────────────────────────────────────────────────────
29
+ # Check 1: API Routes without UI consumers
30
+ # ─────────────────────────────────────────────────────────────
31
+
32
+ echo "📋 Checking API routes..."
33
+
34
+ # Find API route files (Next.js style)
35
+ API_ROUTES=$(find . -path "*/api/*" -name "*.ts" -o -path "*/api/*" -name "*.tsx" 2>/dev/null | grep -v node_modules || true)
36
+
37
+ if [ -n "$API_ROUTES" ]; then
38
+ while IFS= read -r route; do
39
+ # Extract endpoint path from file path
40
+ endpoint=$(echo "$route" | sed 's|.*api/||' | sed 's|/route\.\(ts\|tsx\)||' | sed 's|\.\(ts\|tsx\)||')
41
+
42
+ # Check if any component imports or fetches this endpoint
43
+ if [ -n "$endpoint" ]; then
44
+ USAGE=$(grep -r "/api/$endpoint" --include="*.tsx" --include="*.ts" . 2>/dev/null | grep -v "api/" | grep -v node_modules || true)
45
+
46
+ if [ -z "$USAGE" ]; then
47
+ echo -e " ${RED}⛔ Orphan API: /api/$endpoint${NC}"
48
+ echo " File: $route"
49
+ echo " No UI component calls this endpoint"
50
+ ORPHANS_FOUND=1
51
+ fi
52
+ fi
53
+ done <<< "$API_ROUTES"
54
+
55
+ if [ $ORPHANS_FOUND -eq 0 ]; then
56
+ echo -e " ${GREEN}✓ All API routes have UI consumers${NC}"
57
+ fi
58
+ else
59
+ echo -e " ${CYAN}○ No API routes found (or not using /api/ pattern)${NC}"
60
+ fi
61
+
62
+ echo ""
63
+
64
+ # ─────────────────────────────────────────────────────────────
65
+ # Check 2: Hooks not used by any component
66
+ # ─────────────────────────────────────────────────────────────
67
+
68
+ echo "📋 Checking custom hooks..."
69
+
70
+ # Find hook files
71
+ HOOKS=$(find . -path "*/hooks/*" -name "use*.ts" -o -path "*/hooks/*" -name "use*.tsx" 2>/dev/null | grep -v node_modules || true)
72
+
73
+ if [ -n "$HOOKS" ]; then
74
+ while IFS= read -r hook; do
75
+ # Extract hook name
76
+ hook_name=$(basename "$hook" | sed 's/\.\(ts\|tsx\)//')
77
+
78
+ # Check if hook is imported anywhere
79
+ USAGE=$(grep -r "from.*hooks.*$hook_name\|import.*$hook_name" --include="*.tsx" --include="*.ts" . 2>/dev/null | grep -v "hooks/" | grep -v node_modules | grep -v ".test." || true)
80
+
81
+ if [ -z "$USAGE" ]; then
82
+ echo -e " ${RED}⛔ Unused Hook: $hook_name${NC}"
83
+ echo " File: $hook"
84
+ echo " Not imported by any component"
85
+ ORPHANS_FOUND=1
86
+ fi
87
+ done <<< "$HOOKS"
88
+
89
+ if [ $ORPHANS_FOUND -eq 0 ]; then
90
+ echo -e " ${GREEN}✓ All hooks are used${NC}"
91
+ fi
92
+ else
93
+ echo -e " ${CYAN}○ No custom hooks found${NC}"
94
+ fi
95
+
96
+ echo ""
97
+
98
+ # ─────────────────────────────────────────────────────────────
99
+ # Check 3: Utility functions not imported
100
+ # ─────────────────────────────────────────────────────────────
101
+
102
+ echo "📋 Checking utility functions..."
103
+
104
+ # Find utility files (excluding index and test files)
105
+ UTILS=$(find . -path "*/lib/*" -name "*.ts" -o -path "*/utils/*" -name "*.ts" 2>/dev/null | grep -v node_modules | grep -v "index.ts" | grep -v ".test." | grep -v ".spec." || true)
106
+
107
+ if [ -n "$UTILS" ]; then
108
+ UNUSED_UTILS=0
109
+ while IFS= read -r util; do
110
+ # Extract file name without extension
111
+ util_name=$(basename "$util" .ts)
112
+
113
+ # Check if utility is imported anywhere
114
+ USAGE=$(grep -r "from.*\(lib\|utils\).*$util_name\|import.*$util_name" --include="*.tsx" --include="*.ts" . 2>/dev/null | grep -v "lib/" | grep -v "utils/" | grep -v node_modules || true)
115
+
116
+ if [ -z "$USAGE" ]; then
117
+ echo -e " ${YELLOW}⚠ Potentially unused: $util_name${NC}"
118
+ echo " File: $util"
119
+ UNUSED_UTILS=1
120
+ fi
121
+ done <<< "$UTILS"
122
+
123
+ if [ $UNUSED_UTILS -eq 0 ]; then
124
+ echo -e " ${GREEN}✓ All utilities appear to be used${NC}"
125
+ fi
126
+ else
127
+ echo -e " ${CYAN}○ No utility files found${NC}"
128
+ fi
129
+
130
+ echo ""
131
+
132
+ # ─────────────────────────────────────────────────────────────
133
+ # Check 4: Pages without routes (for file-based routing)
134
+ # ─────────────────────────────────────────────────────────────
135
+
136
+ echo "📋 Checking page accessibility..."
137
+
138
+ # This is a basic check - can be expanded based on routing system
139
+ PAGES=$(find . -path "*/pages/*" -name "*.tsx" -o -path "*/app/*" -name "page.tsx" 2>/dev/null | grep -v node_modules | grep -v "_app" | grep -v "_document" | grep -v "layout" || true)
140
+
141
+ if [ -n "$PAGES" ]; then
142
+ echo -e " ${GREEN}✓ Found $(echo "$PAGES" | wc -l | tr -d ' ') page(s)${NC}"
143
+ # Note: Actual route accessibility check would require analyzing router config
144
+ else
145
+ echo -e " ${CYAN}○ No page files found (or using different routing)${NC}"
146
+ fi
147
+
148
+ echo ""
149
+
150
+ # ─────────────────────────────────────────────────────────────
151
+ # Summary
152
+ # ─────────────────────────────────────────────────────────────
153
+
154
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
155
+
156
+ if [ $ORPHANS_FOUND -eq 1 ]; then
157
+ echo -e "${RED}⛔ UI ENFORCEMENT FAILED${NC}"
158
+ echo ""
159
+ echo "Orphan features detected. Per the workflow rules:"
160
+ echo ""
161
+ echo " FEATURE IS NOT COMPLETE UNLESS:"
162
+ echo " ├── Backend (API/logic) ✓"
163
+ echo " ├── Frontend (UI component) ✓ ← REQUIRED"
164
+ echo " ├── Connection (UI calls API) ✓"
165
+ echo " └── Access (user can reach it) ✓"
166
+ echo ""
167
+ echo -e "${YELLOW}Fix: Add UI components for orphan features before committing.${NC}"
168
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
169
+ exit 1
170
+ else
171
+ echo -e "${GREEN}✅ UI ENFORCEMENT PASSED${NC}"
172
+ echo ""
173
+ echo "No orphan features detected."
174
+ echo "All backend features have corresponding UI."
175
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
176
+ exit 0
177
+ fi
@@ -0,0 +1,116 @@
1
+ #!/bin/bash
2
+ # ensure-no-errors.sh
3
+ # Pre-commit verification - blocks commits if errors exist
4
+
5
+ set -e
6
+
7
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8
+ PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
9
+
10
+ # Colors
11
+ RED='\033[0;31m'
12
+ GREEN='\033[0;32m'
13
+ YELLOW='\033[1;33m'
14
+ NC='\033[0m'
15
+
16
+ cd "$PROJECT_ROOT"
17
+
18
+ echo "🔒 Pre-commit verification..."
19
+ echo ""
20
+
21
+ BLOCKED=0
22
+
23
+ # ─────────────────────────────────────────────────────────────
24
+ # TypeScript Check
25
+ # ─────────────────────────────────────────────────────────────
26
+
27
+ echo "📋 TypeScript check..."
28
+ TSC_OUTPUT=$(npm run typecheck 2>&1) || true
29
+
30
+ if echo "$TSC_OUTPUT" | grep -q "error TS"; then
31
+ ERROR_COUNT=$(echo "$TSC_OUTPUT" | grep -c "error TS" || echo "0")
32
+ echo -e "${RED}❌ Found $ERROR_COUNT TypeScript error(s)${NC}"
33
+ echo "$TSC_OUTPUT" | grep "error TS" | head -10
34
+ BLOCKED=1
35
+ else
36
+ echo -e "${GREEN}✓ TypeScript: OK${NC}"
37
+ fi
38
+
39
+ # ─────────────────────────────────────────────────────────────
40
+ # ESLint Check
41
+ # ─────────────────────────────────────────────────────────────
42
+
43
+ echo ""
44
+ echo "📋 ESLint check..."
45
+ LINT_OUTPUT=$(npm run lint 2>&1) || true
46
+
47
+ if echo "$LINT_OUTPUT" | grep -qE "[0-9]+ error|[0-9]+ warning"; then
48
+ echo -e "${RED}❌ ESLint issues found${NC}"
49
+ echo "$LINT_OUTPUT" | tail -5
50
+ BLOCKED=1
51
+ else
52
+ echo -e "${GREEN}✓ ESLint: OK${NC}"
53
+ fi
54
+
55
+ # ─────────────────────────────────────────────────────────────
56
+ # TODO/FIXME Check
57
+ # ─────────────────────────────────────────────────────────────
58
+
59
+ echo ""
60
+ echo "📋 Checking for TODO/FIXME..."
61
+ STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM 2>/dev/null | grep -E "\.(ts|tsx|js|jsx)$" || true)
62
+
63
+ if [ -n "$STAGED_FILES" ]; then
64
+ TODO_FOUND=$(echo "$STAGED_FILES" | xargs grep -l "TODO\|FIXME\|XXX\|HACK" 2>/dev/null || true)
65
+ if [ -n "$TODO_FOUND" ]; then
66
+ echo -e "${RED}❌ Found TODO/FIXME in:${NC}"
67
+ echo "$TODO_FOUND"
68
+ BLOCKED=1
69
+ else
70
+ echo -e "${GREEN}✓ No TODO/FIXME${NC}"
71
+ fi
72
+ else
73
+ echo -e "${GREEN}✓ No TODO/FIXME${NC}"
74
+ fi
75
+
76
+ # ─────────────────────────────────────────────────────────────
77
+ # Console.log Check
78
+ # ─────────────────────────────────────────────────────────────
79
+
80
+ echo ""
81
+ echo "📋 Checking for console.log..."
82
+
83
+ if [ -n "$STAGED_FILES" ]; then
84
+ CONSOLE_FOUND=$(echo "$STAGED_FILES" | xargs grep -l "console\.\(log\|debug\|info\)" 2>/dev/null || true)
85
+ if [ -n "$CONSOLE_FOUND" ]; then
86
+ echo -e "${RED}❌ Found console.log in:${NC}"
87
+ echo "$CONSOLE_FOUND"
88
+ BLOCKED=1
89
+ else
90
+ echo -e "${GREEN}✓ No console.log${NC}"
91
+ fi
92
+ else
93
+ echo -e "${GREEN}✓ No console.log${NC}"
94
+ fi
95
+
96
+ # ─────────────────────────────────────────────────────────────
97
+ # Result
98
+ # ─────────────────────────────────────────────────────────────
99
+
100
+ echo ""
101
+
102
+ if [ $BLOCKED -eq 1 ]; then
103
+ echo -e "${RED}╔══════════════════════════════════════════════════════════════╗${NC}"
104
+ echo -e "${RED}║ COMMIT BLOCKED ║${NC}"
105
+ echo -e "${RED}╠══════════════════════════════════════════════════════════════╣${NC}"
106
+ echo -e "${RED}║ Fix the issues above before committing. ║${NC}"
107
+ echo -e "${RED}║ ║${NC}"
108
+ echo -e "${RED}║ Commands: ║${NC}"
109
+ echo -e "${RED}║ npm run typecheck - Check TypeScript errors ║${NC}"
110
+ echo -e "${RED}║ npm run lint:fix - Auto-fix ESLint issues ║${NC}"
111
+ echo -e "${RED}╚══════════════════════════════════════════════════════════════╝${NC}"
112
+ exit 1
113
+ fi
114
+
115
+ echo -e "${GREEN}✅ All pre-commit checks passed${NC}"
116
+ exit 0