Restructure QA output for maximum actionability
Complete rewrite of output format: 1. PRIORITY FILES section: - Shows files with CRITICAL/HIGH issues sorted by count - Breaks down severity per file: "file.sh (CRITICAL: 2, HIGH: 5)" - Calculates coverage: "Fix top 3 files = 50% of issues" - Immediately answers: "Which files should I fix first?" 2. HIGH ISSUES grouped BY FILE: - Shows first 3 issues per file with line numbers - Displays total count: "file.sh (12 issues)" - Groups related issues together for batch fixing - Much easier to work through file-by-file 3. QUICK WINS section: - Shows patterns appearing 10+ times - Provides fix description for each pattern - Example: "15 × SOURCE - Add existence checks before sourcing" - Identifies opportunities to fix many issues at once 4. MEDIUM/LOW collapsed: - Single summary line (not pages of low-priority detail) - Provides grep command to view when needed Benefits for AI/human readers: - Answers "where do I start?" immediately - Groups issues by file (actionable context) - Shows impact (% coverage of top files) - Identifies patterns (fix 15 issues with one approach) - Reduces noise (no pages of MEDIUM/LOW details) - Clear hierarchy: PRIORITY → CRITICAL → HIGH → QUICK WINS Output is now optimized for taking action, not just reporting.
This commit is contained in:
+86
-35
@@ -3318,9 +3318,42 @@ fi
|
|||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# CRITICAL issues: Show ALL (no truncation)
|
# PRIORITY FILES: Show which files have CRITICAL/HIGH issues
|
||||||
|
if [ "$crit" -gt 0 ] || [ "$high" -gt 0 ]; then
|
||||||
|
echo -e "${BOLD}PRIORITY FILES (CRITICAL/HIGH issues):${NC}"
|
||||||
|
{
|
||||||
|
[ "$crit" -gt 0 ] && grep "^CRITICAL|" "$REPORT" | cut -d'|' -f2
|
||||||
|
[ "$high" -gt 0 ] && grep "^HIGH|" "$REPORT" | cut -d'|' -f2
|
||||||
|
} | sed "s|$TOOLKIT_PATH/||" | sort | uniq -c | sort -rn | head -10 | while read count file; do
|
||||||
|
# Get breakdown by severity for this file
|
||||||
|
crit_in_file=$(grep "^CRITICAL|.*${file}" "$REPORT" 2>/dev/null | wc -l)
|
||||||
|
high_in_file=$(grep "^HIGH|.*${file}" "$REPORT" 2>/dev/null | wc -l)
|
||||||
|
|
||||||
|
if [ "$crit_in_file" -gt 0 ]; then
|
||||||
|
printf " ${RED}●${NC} %s ${RED}(CRITICAL: %d, HIGH: %d)${NC}\n" "$file" "$crit_in_file" "$high_in_file"
|
||||||
|
else
|
||||||
|
printf " ${YELLOW}●${NC} %s ${YELLOW}(HIGH: %d)${NC}\n" "$file" "$high_in_file"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Calculate coverage
|
||||||
|
total_priority=$((crit + high))
|
||||||
|
top3_count=$(
|
||||||
|
{
|
||||||
|
[ "$crit" -gt 0 ] && grep "^CRITICAL|" "$REPORT" | cut -d'|' -f2
|
||||||
|
[ "$high" -gt 0 ] && grep "^HIGH|" "$REPORT" | cut -d'|' -f2
|
||||||
|
} | sed "s|$TOOLKIT_PATH/||" | sort | uniq -c | sort -rn | head -3 | awk '{sum+=$1} END {print sum}'
|
||||||
|
)
|
||||||
|
if [ "$total_priority" -gt 0 ] && [ -n "$top3_count" ] && [ "$top3_count" -gt 0 ]; then
|
||||||
|
coverage=$((top3_count * 100 / total_priority))
|
||||||
|
echo -e " ${DIM}→ Fix top 3 files = ${coverage}% of CRITICAL/HIGH issues${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# CRITICAL issues grouped by file
|
||||||
if [ "$crit" -gt 0 ]; then
|
if [ "$crit" -gt 0 ]; then
|
||||||
echo -e "${RED}${BOLD}CRITICAL ISSUES ($crit) - MUST FIX:${NC}"
|
echo -e "${RED}${BOLD}CRITICAL ISSUES ($crit) - MUST FIX IMMEDIATELY:${NC}"
|
||||||
grep "^CRITICAL|" "$REPORT" | while IFS='|' read -r sev file line issue; do
|
grep "^CRITICAL|" "$REPORT" | while IFS='|' read -r sev file line issue; do
|
||||||
rel_file="${file#$TOOLKIT_PATH/}"
|
rel_file="${file#$TOOLKIT_PATH/}"
|
||||||
printf " ${RED}●${NC} %s:%s - %s\n" "$rel_file" "$line" "$issue"
|
printf " ${RED}●${NC} %s:%s - %s\n" "$rel_file" "$line" "$issue"
|
||||||
@@ -3328,50 +3361,68 @@ if [ "$crit" -gt 0 ]; then
|
|||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# HIGH issues: Show top 20, group by file
|
# HIGH issues: Group by file for easier action
|
||||||
if [ "$high" -gt 0 ]; then
|
if [ "$high" -gt 0 ]; then
|
||||||
echo -e "${YELLOW}${BOLD}HIGH ISSUES ($high) - FIX SOON:${NC}"
|
echo -e "${YELLOW}${BOLD}HIGH ISSUES BY FILE (showing top 15 issues):${NC}"
|
||||||
grep "^HIGH|" "$REPORT" | head -20 | while IFS='|' read -r sev file line issue; do
|
|
||||||
rel_file="${file#$TOOLKIT_PATH/}"
|
# Get unique files with HIGH issues
|
||||||
printf " ${YELLOW}●${NC} %s:%s - %s\n" "$rel_file" "$line" "$issue"
|
high_files=$(grep "^HIGH|" "$REPORT" | cut -d'|' -f2 | sed "s|$TOOLKIT_PATH/||" | sort -u)
|
||||||
|
|
||||||
|
shown=0
|
||||||
|
echo "$high_files" | while read -r rel_file; do
|
||||||
|
[ "$shown" -ge 15 ] && break
|
||||||
|
|
||||||
|
# Count issues in this file
|
||||||
|
file_high_count=$(grep "^HIGH|.*${rel_file}" "$REPORT" 2>/dev/null | wc -l)
|
||||||
|
|
||||||
|
# Show first 3 issues from this file
|
||||||
|
echo -e " ${YELLOW}${rel_file}${NC} ${DIM}($file_high_count issues)${NC}"
|
||||||
|
grep "^HIGH|.*${rel_file}" "$REPORT" | head -3 | while IFS='|' read -r sev file line issue; do
|
||||||
|
printf " %s ${DIM}- %s${NC}\n" "$line" "$issue"
|
||||||
|
shown=$((shown + 1))
|
||||||
done
|
done
|
||||||
if [ "$high" -gt 20 ]; then
|
[ "$file_high_count" -gt 3 ] && echo -e " ${DIM}... +$((file_high_count - 3)) more in this file${NC}"
|
||||||
echo -e " ${DIM}... +$((high - 20)) more (run: grep '^HIGH' $REPORT)${NC}"
|
done
|
||||||
|
|
||||||
|
if [ "$high" -gt 15 ]; then
|
||||||
|
echo -e " ${DIM}... +$((high - 15)) more issues (run: grep '^HIGH' $REPORT)${NC}"
|
||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# MEDIUM/LOW: Just show file counts
|
# QUICK WINS: Show patterns that appear frequently (easy to fix multiple at once)
|
||||||
if [ "$med" -gt 0 ] || [ "$low" -gt 0 ]; then
|
|
||||||
echo -e "${BOLD}MEDIUM ($med) & LOW ($low) ISSUES BY FILE:${NC}"
|
|
||||||
{
|
|
||||||
grep "^MEDIUM|" "$REPORT" 2>/dev/null | cut -d'|' -f2
|
|
||||||
grep "^LOW|" "$REPORT" 2>/dev/null | cut -d'|' -f2
|
|
||||||
} | sed "s|$TOOLKIT_PATH/||" | sort | uniq -c | sort -rn | head -15 | while read count file; do
|
|
||||||
printf " ${DIM}%3d issues${NC} - %s\n" "$count" "$file"
|
|
||||||
done
|
|
||||||
echo -e " ${DIM}(Run: grep '^MEDIUM\\|^LOW' $REPORT | less)${NC}"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Top issue categories (compact view)
|
|
||||||
if [ "$total" -gt 0 ]; then
|
if [ "$total" -gt 0 ]; then
|
||||||
echo -e "${BOLD}TOP 10 ISSUE CATEGORIES:${NC}"
|
echo -e "${BOLD}QUICK WINS (patterns appearing 10+ times):${NC}"
|
||||||
declare -A cat_counts
|
quick_wins_found=0
|
||||||
for tag in SQL-INJ CMD-INJ PANEL-CALL FILE-OP SECRET-LEAK RACE SOURCE RETURN NULL DEP TEMP SUBSHELL PIPE WORDSPLIT ARITH TEST REDIR TRAP ARRAY HEREDOC IF-MASK NUMCMP BG-JOB LOCALE PROC-SUB PRINTF REGEX BASHISM ESCAPE SLEEP-RACE IFS SUBSHELL-VAR TRAP-RACE PERF-LOOP PERF-CACHE PERF-READ RECURSION FD-LEAK ZOMBIE DISK-SPACE NET-TIMEOUT LOG-ROTATE CPU-LOOP HARDCODED-PATH MISSING-LIB USERDATA-ACCESS API-CHECK NO-CASE DB-PATTERN NO-USER-MGR NO-STANDALONE; do
|
|
||||||
|
# Check for common patterns
|
||||||
|
for tag in SOURCE TEMP HARDCODED-PATH WORDSPLIT NULL PIPE SUBSHELL; do
|
||||||
count=$(grep -c "\[$tag\]" "$REPORT" 2>/dev/null || echo 0)
|
count=$(grep -c "\[$tag\]" "$REPORT" 2>/dev/null || echo 0)
|
||||||
# Sanitize: ensure it's a single integer
|
|
||||||
count=$(echo "$count" | head -1 | tr -d '\n\r' | grep -o '^[0-9]*$' || echo 0)
|
count=$(echo "$count" | head -1 | tr -d '\n\r' | grep -o '^[0-9]*$' || echo 0)
|
||||||
[ "$count" -gt 0 ] 2>/dev/null && cat_counts[$tag]=$count
|
|
||||||
|
if [ "$count" -ge 10 ] 2>/dev/null; then
|
||||||
|
quick_wins_found=1
|
||||||
|
case "$tag" in
|
||||||
|
SOURCE) desc="Add existence checks before sourcing files" ;;
|
||||||
|
TEMP) desc="Use mktemp instead of hardcoded /tmp paths" ;;
|
||||||
|
HARDCODED-PATH) desc="Replace hardcoded paths with detection" ;;
|
||||||
|
WORDSPLIT) desc="Quote variable expansions" ;;
|
||||||
|
NULL) desc="Add empty checks before using variables" ;;
|
||||||
|
PIPE) desc="Avoid useless pipes (use grep -q directly)" ;;
|
||||||
|
SUBSHELL) desc="Export variables to subshells" ;;
|
||||||
|
*) desc="Fix $tag pattern" ;;
|
||||||
|
esac
|
||||||
|
printf " ${CYAN}%3d ×${NC} %-20s ${DIM}%s${NC}\n" "$count" "$tag" "$desc"
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ ${#cat_counts[@]} -gt 0 ]; then
|
[ "$quick_wins_found" -eq 0 ] && echo -e " ${DIM}No high-frequency patterns found${NC}"
|
||||||
for tag in "${!cat_counts[@]}"; do
|
echo ""
|
||||||
echo "${cat_counts[$tag]} $tag"
|
fi
|
||||||
done | sort -rn | head -10 | while read count tag; do
|
|
||||||
printf " %-18s %3d issues\n" "$tag" "$count"
|
# MEDIUM/LOW summary (compact)
|
||||||
done
|
if [ "$med" -gt 0 ] || [ "$low" -gt 0 ]; then
|
||||||
fi
|
echo -e "${DIM}MEDIUM: $med issues | LOW: $low issues | Full details: grep '^MEDIUM\\|^LOW' $REPORT${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user