autoworkflow 1.1.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.
- package/.claude/commands/analyze.md +77 -0
- package/.claude/commands/audit.md +220 -0
- package/.claude/commands/build.md +159 -0
- package/.claude/commands/commit.md +165 -0
- package/.claude/commands/fix.md +119 -0
- package/.claude/commands/plan.md +101 -0
- package/.claude/commands/suggest.md +195 -0
- package/.claude/commands/verify.md +113 -0
- package/.claude/settings.json +129 -0
- package/.claude/settings.local.json +9 -0
- package/.prettierrc +11 -0
- package/.vscode/extensions.json +27 -0
- package/.vscode/settings.json +69 -0
- package/.vscode/tasks.json +161 -0
- package/CLAUDE.md +344 -0
- package/README.md +180 -195
- package/eslint.config.example.js +83 -0
- package/hooks/commit-msg +137 -0
- package/hooks/pre-commit +152 -0
- package/instructions/AI_RULES.md +284 -0
- package/instructions/BLUEPRINT.md +170 -0
- package/instructions/CLAUDE.md +472 -0
- package/package.json +45 -45
- package/scripts/autoworkflow.sh +324 -0
- package/scripts/check-ui-enforcement.sh +177 -0
- package/scripts/ensure-no-errors.sh +116 -0
- package/scripts/run-verification.sh +112 -0
- package/scripts/setup.sh +201 -0
- package/system/gates.md +390 -0
- package/system/loops.md +348 -0
- package/system/router.md +415 -0
- package/system/triggers.md +369 -0
- package/tsconfig.example.json +52 -0
- package/bin/cli.js +0 -299
- package/lib/index.js +0 -9
- package/lib/install.js +0 -600
|
@@ -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
|