autoworkflow 3.0.0 → 3.1.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/hooks/audit-runner.sh +191 -0
- package/.claude/hooks/blueprint-generator.sh +253 -0
- package/.claude/hooks/phase-transition.sh +279 -0
- package/.claude/hooks/post-edit.sh +218 -14
- package/.claude/hooks/pre-commit-check.sh +222 -41
- package/.claude/hooks/pre-tool-router.sh +67 -0
- package/.claude/hooks/session-check.sh +328 -41
- package/.claude/settings.json +78 -21
- package/.claude/settings.local.json +5 -1
- package/CLAUDE.md +145 -49
- package/bin/cli.js +9 -1
- package/instructions/CLAUDE.md +22 -0
- package/package.json +1 -1
- package/system/triggers.md +243 -235
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# AutoWorkflow Audit Runner
|
|
3
|
+
# Purpose: Run all audit checks and track results
|
|
4
|
+
#
|
|
5
|
+
# This hook implements audit_loop from system/loops.md
|
|
6
|
+
|
|
7
|
+
# Colors
|
|
8
|
+
RED='\033[0;31m'
|
|
9
|
+
GREEN='\033[0;32m'
|
|
10
|
+
YELLOW='\033[1;33m'
|
|
11
|
+
CYAN='\033[0;36m'
|
|
12
|
+
BOLD='\033[1m'
|
|
13
|
+
DIM='\033[2m'
|
|
14
|
+
NC='\033[0m'
|
|
15
|
+
|
|
16
|
+
# State directory
|
|
17
|
+
STATE_DIR=".claude/.autoworkflow"
|
|
18
|
+
mkdir -p "$STATE_DIR"
|
|
19
|
+
|
|
20
|
+
# Configuration
|
|
21
|
+
MAX_ITERATIONS=5
|
|
22
|
+
AUDIT_ITERATION_FILE="$STATE_DIR/audit-iteration"
|
|
23
|
+
AUDIT_STATUS_FILE="$STATE_DIR/audit-status"
|
|
24
|
+
|
|
25
|
+
# Get current iteration
|
|
26
|
+
get_iteration() {
|
|
27
|
+
if [ -f "$AUDIT_ITERATION_FILE" ]; then
|
|
28
|
+
cat "$AUDIT_ITERATION_FILE"
|
|
29
|
+
else
|
|
30
|
+
echo "0"
|
|
31
|
+
fi
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# Increment iteration
|
|
35
|
+
increment_iteration() {
|
|
36
|
+
local current=$(get_iteration)
|
|
37
|
+
local next=$((current + 1))
|
|
38
|
+
echo "$next" > "$AUDIT_ITERATION_FILE"
|
|
39
|
+
echo "$next"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
# Reset iteration
|
|
43
|
+
reset_iteration() {
|
|
44
|
+
echo "0" > "$AUDIT_ITERATION_FILE"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# Print header
|
|
48
|
+
print_header() {
|
|
49
|
+
local iteration=$(get_iteration)
|
|
50
|
+
echo ""
|
|
51
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
52
|
+
echo -e "${BOLD}AUTOWORKFLOW: AUDIT LOOP${NC} ${DIM}(Iteration $iteration/$MAX_ITERATIONS)${NC}"
|
|
53
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
54
|
+
echo ""
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
# Run UI enforcement check
|
|
58
|
+
run_ui_check() {
|
|
59
|
+
echo -e "${CYAN}[1/2]${NC} UI Enforcement Check"
|
|
60
|
+
|
|
61
|
+
if [ -f "package.json" ] && grep -q '"audit:ui"' package.json 2>/dev/null; then
|
|
62
|
+
echo -e " Command: npm run audit:ui"
|
|
63
|
+
echo ""
|
|
64
|
+
|
|
65
|
+
local output=$(npm run audit:ui 2>&1)
|
|
66
|
+
local exit_code=$?
|
|
67
|
+
|
|
68
|
+
if [ $exit_code -eq 0 ] && ! echo "$output" | grep -qi "orphan\|missing\|error"; then
|
|
69
|
+
echo -e " Result: ${GREEN}✅ PASSED${NC}"
|
|
70
|
+
echo ""
|
|
71
|
+
return 0
|
|
72
|
+
else
|
|
73
|
+
echo -e " Result: ${RED}⛔ FAILED${NC}"
|
|
74
|
+
echo ""
|
|
75
|
+
echo " Orphan features detected:"
|
|
76
|
+
echo "$output" | grep -iE "orphan|missing|error" | while read -r line; do
|
|
77
|
+
echo " → $line"
|
|
78
|
+
done
|
|
79
|
+
echo ""
|
|
80
|
+
return 1
|
|
81
|
+
fi
|
|
82
|
+
else
|
|
83
|
+
echo -e " ${YELLOW}⚠${NC} No audit:ui script found - skipping"
|
|
84
|
+
echo ""
|
|
85
|
+
return 0
|
|
86
|
+
fi
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
# Run circular dependency check
|
|
90
|
+
run_cycle_check() {
|
|
91
|
+
echo -e "${CYAN}[2/2]${NC} Circular Dependencies Check"
|
|
92
|
+
|
|
93
|
+
if [ -f "package.json" ] && grep -q '"audit:cycles"' package.json 2>/dev/null; then
|
|
94
|
+
echo -e " Command: npm run audit:cycles"
|
|
95
|
+
echo ""
|
|
96
|
+
|
|
97
|
+
local output=$(npm run audit:cycles 2>&1)
|
|
98
|
+
local exit_code=$?
|
|
99
|
+
|
|
100
|
+
if [ $exit_code -eq 0 ] && ! echo "$output" | grep -qi "circular\|cycle"; then
|
|
101
|
+
echo -e " Result: ${GREEN}✅ PASSED${NC}"
|
|
102
|
+
echo ""
|
|
103
|
+
return 0
|
|
104
|
+
else
|
|
105
|
+
echo -e " Result: ${RED}⛔ FAILED${NC}"
|
|
106
|
+
echo ""
|
|
107
|
+
echo " Circular dependencies found:"
|
|
108
|
+
echo "$output" | grep -iE "circular|cycle" | while read -r line; do
|
|
109
|
+
echo " → $line"
|
|
110
|
+
done
|
|
111
|
+
echo ""
|
|
112
|
+
return 1
|
|
113
|
+
fi
|
|
114
|
+
else
|
|
115
|
+
echo -e " ${YELLOW}⚠${NC} No audit:cycles script found - skipping"
|
|
116
|
+
echo ""
|
|
117
|
+
return 0
|
|
118
|
+
fi
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
# Main execution
|
|
122
|
+
main() {
|
|
123
|
+
local iteration=$(increment_iteration)
|
|
124
|
+
|
|
125
|
+
# Check max iterations
|
|
126
|
+
if [ "$iteration" -gt "$MAX_ITERATIONS" ]; then
|
|
127
|
+
echo ""
|
|
128
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
129
|
+
echo -e "${RED}${BOLD}⛔ MAX AUDIT ITERATIONS REACHED${NC}"
|
|
130
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
131
|
+
echo ""
|
|
132
|
+
echo "Audit has failed $MAX_ITERATIONS times."
|
|
133
|
+
echo "Manual intervention required."
|
|
134
|
+
echo ""
|
|
135
|
+
echo "BLOCKED" > "$AUDIT_STATUS_FILE"
|
|
136
|
+
exit 1
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
print_header
|
|
140
|
+
|
|
141
|
+
local ui_pass=true
|
|
142
|
+
local cycle_pass=true
|
|
143
|
+
|
|
144
|
+
# Run checks
|
|
145
|
+
if ! run_ui_check; then
|
|
146
|
+
ui_pass=false
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
if ! run_cycle_check; then
|
|
150
|
+
cycle_pass=false
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
154
|
+
|
|
155
|
+
if [ "$ui_pass" = true ] && [ "$cycle_pass" = true ]; then
|
|
156
|
+
echo -e "${GREEN}${BOLD}✅ ALL AUDITS PASSED${NC}"
|
|
157
|
+
echo ""
|
|
158
|
+
echo "Ready to proceed to COMMIT."
|
|
159
|
+
echo ""
|
|
160
|
+
|
|
161
|
+
reset_iteration
|
|
162
|
+
echo "PASSED" > "$AUDIT_STATUS_FILE"
|
|
163
|
+
|
|
164
|
+
# Update phase
|
|
165
|
+
echo "PRE_COMMIT" > "$STATE_DIR/phase"
|
|
166
|
+
|
|
167
|
+
exit 0
|
|
168
|
+
else
|
|
169
|
+
echo -e "${RED}${BOLD}⛔ AUDIT FAILED${NC} ${DIM}(Iteration $iteration/$MAX_ITERATIONS)${NC}"
|
|
170
|
+
echo ""
|
|
171
|
+
|
|
172
|
+
if [ "$ui_pass" = false ]; then
|
|
173
|
+
echo " ☐ Fix orphan features (add missing UI)"
|
|
174
|
+
fi
|
|
175
|
+
|
|
176
|
+
if [ "$cycle_pass" = false ]; then
|
|
177
|
+
echo " ☐ Resolve circular dependencies"
|
|
178
|
+
fi
|
|
179
|
+
|
|
180
|
+
echo ""
|
|
181
|
+
echo "Fix the issues above and run audit again."
|
|
182
|
+
echo -e "${DIM}Remaining attempts: $((MAX_ITERATIONS - iteration))${NC}"
|
|
183
|
+
echo ""
|
|
184
|
+
|
|
185
|
+
echo "FAILED" > "$AUDIT_STATUS_FILE"
|
|
186
|
+
|
|
187
|
+
exit 1
|
|
188
|
+
fi
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
main
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# AutoWorkflow Blueprint Generator
|
|
3
|
+
# Purpose: Auto-scan project and generate BLUEPRINT.md
|
|
4
|
+
#
|
|
5
|
+
# This hook implements on:blueprint_missing trigger from system/triggers.md
|
|
6
|
+
# It runs AUTOMATICALLY without asking permission to start
|
|
7
|
+
|
|
8
|
+
# Colors
|
|
9
|
+
RED='\033[0;31m'
|
|
10
|
+
GREEN='\033[0;32m'
|
|
11
|
+
YELLOW='\033[1;33m'
|
|
12
|
+
CYAN='\033[0;36m'
|
|
13
|
+
BOLD='\033[1m'
|
|
14
|
+
DIM='\033[2m'
|
|
15
|
+
NC='\033[0m'
|
|
16
|
+
|
|
17
|
+
# State directory
|
|
18
|
+
STATE_DIR=".claude/.autoworkflow"
|
|
19
|
+
mkdir -p "$STATE_DIR"
|
|
20
|
+
|
|
21
|
+
# Output file
|
|
22
|
+
SCAN_OUTPUT="$STATE_DIR/project-scan.txt"
|
|
23
|
+
|
|
24
|
+
print_header() {
|
|
25
|
+
echo ""
|
|
26
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
27
|
+
echo -e "${BOLD}AUTOWORKFLOW: PROJECT AUDIT${NC}"
|
|
28
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
29
|
+
echo ""
|
|
30
|
+
echo "Scanning project to generate BLUEPRINT.md..."
|
|
31
|
+
echo ""
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# Detect tech stack from package.json
|
|
35
|
+
detect_tech_stack() {
|
|
36
|
+
echo -e "${CYAN}[1/6]${NC} Detecting tech stack..."
|
|
37
|
+
|
|
38
|
+
if [ -f "package.json" ]; then
|
|
39
|
+
echo " Found: package.json"
|
|
40
|
+
|
|
41
|
+
# Detect framework
|
|
42
|
+
if grep -q '"next"' package.json 2>/dev/null; then
|
|
43
|
+
echo " Framework: Next.js"
|
|
44
|
+
elif grep -q '"react"' package.json 2>/dev/null; then
|
|
45
|
+
echo " Framework: React"
|
|
46
|
+
elif grep -q '"vue"' package.json 2>/dev/null; then
|
|
47
|
+
echo " Framework: Vue"
|
|
48
|
+
elif grep -q '"svelte"' package.json 2>/dev/null; then
|
|
49
|
+
echo " Framework: Svelte"
|
|
50
|
+
elif grep -q '"express"' package.json 2>/dev/null; then
|
|
51
|
+
echo " Framework: Express"
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# Detect styling
|
|
55
|
+
if grep -q '"tailwindcss"' package.json 2>/dev/null; then
|
|
56
|
+
echo " Styling: Tailwind CSS"
|
|
57
|
+
elif grep -q '"styled-components"' package.json 2>/dev/null; then
|
|
58
|
+
echo " Styling: styled-components"
|
|
59
|
+
elif grep -q '"@emotion"' package.json 2>/dev/null; then
|
|
60
|
+
echo " Styling: Emotion"
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# Detect database
|
|
64
|
+
if grep -q '"prisma"' package.json 2>/dev/null; then
|
|
65
|
+
echo " Database: Prisma"
|
|
66
|
+
elif grep -q '"mongoose"' package.json 2>/dev/null; then
|
|
67
|
+
echo " Database: MongoDB (Mongoose)"
|
|
68
|
+
elif grep -q '"pg"' package.json 2>/dev/null; then
|
|
69
|
+
echo " Database: PostgreSQL"
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
# Detect TypeScript
|
|
73
|
+
if grep -q '"typescript"' package.json 2>/dev/null; then
|
|
74
|
+
echo " Language: TypeScript"
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
echo ""
|
|
78
|
+
else
|
|
79
|
+
echo " No package.json found"
|
|
80
|
+
echo ""
|
|
81
|
+
fi
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
# Scan project structure
|
|
85
|
+
scan_structure() {
|
|
86
|
+
echo -e "${CYAN}[2/6]${NC} Scanning project structure..."
|
|
87
|
+
|
|
88
|
+
# Find source directory
|
|
89
|
+
if [ -d "src" ]; then
|
|
90
|
+
echo " Source: src/"
|
|
91
|
+
ls -1 src/ 2>/dev/null | head -10 | while read -r item; do
|
|
92
|
+
echo " - $item"
|
|
93
|
+
done
|
|
94
|
+
elif [ -d "app" ]; then
|
|
95
|
+
echo " Source: app/"
|
|
96
|
+
ls -1 app/ 2>/dev/null | head -10 | while read -r item; do
|
|
97
|
+
echo " - $item"
|
|
98
|
+
done
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
echo ""
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
# Scan for routes/pages
|
|
105
|
+
scan_routes() {
|
|
106
|
+
echo -e "${CYAN}[3/6]${NC} Scanning routes..."
|
|
107
|
+
|
|
108
|
+
local found=false
|
|
109
|
+
|
|
110
|
+
# Next.js app router
|
|
111
|
+
if [ -d "src/app" ] || [ -d "app" ]; then
|
|
112
|
+
local app_dir="app"
|
|
113
|
+
[ -d "src/app" ] && app_dir="src/app"
|
|
114
|
+
|
|
115
|
+
echo " Next.js App Router detected"
|
|
116
|
+
find "$app_dir" -name "page.tsx" -o -name "page.js" 2>/dev/null | head -20 | while read -r page; do
|
|
117
|
+
local route=$(dirname "$page" | sed "s|$app_dir||" | sed 's|^/||')
|
|
118
|
+
[ -z "$route" ] && route="/"
|
|
119
|
+
echo " → /$route"
|
|
120
|
+
done
|
|
121
|
+
found=true
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
# Next.js pages router
|
|
125
|
+
if [ -d "src/pages" ] || [ -d "pages" ]; then
|
|
126
|
+
local pages_dir="pages"
|
|
127
|
+
[ -d "src/pages" ] && pages_dir="src/pages"
|
|
128
|
+
|
|
129
|
+
echo " Next.js Pages Router detected"
|
|
130
|
+
find "$pages_dir" -name "*.tsx" -o -name "*.js" 2>/dev/null | grep -v "_app\|_document\|api" | head -20 | while read -r page; do
|
|
131
|
+
local route=$(echo "$page" | sed "s|$pages_dir||" | sed 's|\.tsx$||' | sed 's|\.js$||' | sed 's|/index$||')
|
|
132
|
+
[ -z "$route" ] && route="/"
|
|
133
|
+
echo " → $route"
|
|
134
|
+
done
|
|
135
|
+
found=true
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
if [ "$found" = false ]; then
|
|
139
|
+
echo " No standard route structure detected"
|
|
140
|
+
fi
|
|
141
|
+
|
|
142
|
+
echo ""
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
# Scan for components
|
|
146
|
+
scan_components() {
|
|
147
|
+
echo -e "${CYAN}[4/6]${NC} Scanning components..."
|
|
148
|
+
|
|
149
|
+
local comp_dir=""
|
|
150
|
+
[ -d "src/components" ] && comp_dir="src/components"
|
|
151
|
+
[ -d "components" ] && comp_dir="components"
|
|
152
|
+
|
|
153
|
+
if [ -n "$comp_dir" ]; then
|
|
154
|
+
local count=$(find "$comp_dir" -name "*.tsx" -o -name "*.jsx" 2>/dev/null | wc -l | tr -d ' ')
|
|
155
|
+
echo " Found: $count component(s) in $comp_dir/"
|
|
156
|
+
|
|
157
|
+
find "$comp_dir" -name "*.tsx" -o -name "*.jsx" 2>/dev/null | head -15 | while read -r comp; do
|
|
158
|
+
local name=$(basename "$comp" | sed 's|\.tsx$||' | sed 's|\.jsx$||')
|
|
159
|
+
echo " - $name"
|
|
160
|
+
done
|
|
161
|
+
else
|
|
162
|
+
echo " No components directory found"
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
echo ""
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
# Scan for API endpoints
|
|
169
|
+
scan_api() {
|
|
170
|
+
echo -e "${CYAN}[5/6]${NC} Scanning API endpoints..."
|
|
171
|
+
|
|
172
|
+
local api_dir=""
|
|
173
|
+
[ -d "src/app/api" ] && api_dir="src/app/api"
|
|
174
|
+
[ -d "app/api" ] && api_dir="app/api"
|
|
175
|
+
[ -d "src/pages/api" ] && api_dir="src/pages/api"
|
|
176
|
+
[ -d "pages/api" ] && api_dir="pages/api"
|
|
177
|
+
|
|
178
|
+
if [ -n "$api_dir" ]; then
|
|
179
|
+
echo " API directory: $api_dir/"
|
|
180
|
+
|
|
181
|
+
find "$api_dir" -name "route.ts" -o -name "route.js" -o -name "*.ts" -o -name "*.js" 2>/dev/null | head -20 | while read -r api; do
|
|
182
|
+
local endpoint=$(dirname "$api" | sed "s|$api_dir||")
|
|
183
|
+
[ -z "$endpoint" ] && endpoint="/"
|
|
184
|
+
echo " → /api$endpoint"
|
|
185
|
+
done
|
|
186
|
+
else
|
|
187
|
+
echo " No API directory found"
|
|
188
|
+
fi
|
|
189
|
+
|
|
190
|
+
echo ""
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
# Scan for hooks
|
|
194
|
+
scan_hooks() {
|
|
195
|
+
echo -e "${CYAN}[6/6]${NC} Scanning custom hooks..."
|
|
196
|
+
|
|
197
|
+
local hooks_dir=""
|
|
198
|
+
[ -d "src/hooks" ] && hooks_dir="src/hooks"
|
|
199
|
+
[ -d "hooks" ] && hooks_dir="hooks"
|
|
200
|
+
|
|
201
|
+
if [ -n "$hooks_dir" ]; then
|
|
202
|
+
local count=$(find "$hooks_dir" -name "use*.ts" -o -name "use*.tsx" 2>/dev/null | wc -l | tr -d ' ')
|
|
203
|
+
echo " Found: $count hook(s) in $hooks_dir/"
|
|
204
|
+
|
|
205
|
+
find "$hooks_dir" -name "use*.ts" -o -name "use*.tsx" 2>/dev/null | head -10 | while read -r hook; do
|
|
206
|
+
local name=$(basename "$hook" | sed 's|\.tsx$||' | sed 's|\.ts$||')
|
|
207
|
+
echo " - $name"
|
|
208
|
+
done
|
|
209
|
+
else
|
|
210
|
+
echo " No hooks directory found"
|
|
211
|
+
fi
|
|
212
|
+
|
|
213
|
+
echo ""
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
# Generate summary
|
|
217
|
+
generate_summary() {
|
|
218
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
219
|
+
echo -e "${GREEN}${BOLD}🔍 AUDIT COMPLETE${NC}"
|
|
220
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
221
|
+
echo ""
|
|
222
|
+
echo "Based on this scan, I will generate:"
|
|
223
|
+
echo ""
|
|
224
|
+
echo " 📄 instructions/AI_RULES.md"
|
|
225
|
+
echo " - Tech Stack section (detected above)"
|
|
226
|
+
echo " - File Structure section"
|
|
227
|
+
echo ""
|
|
228
|
+
echo " 📘 instructions/BLUEPRINT.md"
|
|
229
|
+
echo " - Features table (routes + components + APIs)"
|
|
230
|
+
echo " - Routes section"
|
|
231
|
+
echo " - API endpoints section"
|
|
232
|
+
echo ""
|
|
233
|
+
echo -e "${YELLOW}${BOLD}Should I save these files?${NC} (yes/no/edit first)"
|
|
234
|
+
echo ""
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
# Main execution
|
|
238
|
+
main() {
|
|
239
|
+
print_header
|
|
240
|
+
|
|
241
|
+
# Run all scans
|
|
242
|
+
detect_tech_stack
|
|
243
|
+
scan_structure
|
|
244
|
+
scan_routes
|
|
245
|
+
scan_components
|
|
246
|
+
scan_api
|
|
247
|
+
scan_hooks
|
|
248
|
+
|
|
249
|
+
# Generate summary
|
|
250
|
+
generate_summary
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
main
|