diff --git a/MEMORY.md b/MEMORY.md index 578ed3c..4f5275b 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -603,6 +603,14 @@ cd /Users/mattbruce/Documents/Projects/OpenClaw/Web/gantt-board ./scripts/audit-cli-coverage.sh # Script that compares API vs CLI ``` +**Audit Script Template:** +Copy to new projects: +```bash +cp /Users/mattbruce/.openclaw/workspace/scripts/audit-cli-coverage.sh \ + /Users/mattbruce/Documents/Projects/OpenClaw/Web/{new-project}/scripts/ +``` +Then customize the `CLI_MAP` associative array to match your CLI commands. + **If CLI lags behind API → File a bug task immediately.** ## Quick Commands diff --git a/scripts/audit-cli-coverage.sh b/scripts/audit-cli-coverage.sh new file mode 100755 index 0000000..908e1ed --- /dev/null +++ b/scripts/audit-cli-coverage.sh @@ -0,0 +1,150 @@ +#!/bin/bash +# CLI Coverage Audit Script +# Compares API endpoints to CLI commands to ensure sync +# Usage: ./scripts/audit-cli-coverage.sh + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" +API_DIR="${PROJECT_ROOT}/src/app/api" + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +log_info() { echo -e "${GREEN}✓${NC} $1"; } +log_warn() { echo -e "${YELLOW}⚠${NC} $1"; } +log_error() { echo -e "${RED}✗${NC} $1"; } + +echo "═══════════════════════════════════════════════════════════" +echo " CLI Coverage Audit" +echo "═══════════════════════════════════════════════════════════" +echo "" + +# Check if API directory exists +if [ ! -d "$API_DIR" ]; then + log_error "API directory not found: $API_DIR" + exit 1 +fi + +# Find all API route files +echo "📁 Scanning API routes in $API_DIR..." +echo "" + +# Extract API endpoints from route.ts files +declare -a API_ENDPOINTS=() + +while IFS= read -r -d '' route_file; do + # Get the directory path relative to api/ + rel_path=$(dirname "$route_file" | sed "s|$API_DIR/||") + + # Check for HTTP methods in the file + if grep -q "export async function GET" "$route_file"; then + API_ENDPOINTS+=("GET /api/$rel_path") + fi + if grep -q "export async function POST" "$route_file"; then + API_ENDPOINTS+=("POST /api/$rel_path") + fi + if grep -q "export async function PATCH" "$route_file"; then + API_ENDPOINTS+=("PATCH /api/$rel_path") + fi + if grep -q "export async function DELETE" "$route_file"; then + API_ENDPOINTS+=("DELETE /api/$rel_path") + fi + if grep -q "export async function PUT" "$route_file"; then + API_ENDPOINTS+=("PUT /api/$rel_path") + fi +done < <(find "$API_DIR" -name "route.ts" -print0) + +# Sort and dedupe API endpoints +IFS=$'\n' API_ENDPOINTS=($(sort <<< "${API_ENDPOINTS[*]}")) +unset IFS + +echo "Found ${#API_ENDPOINTS[@]} API endpoint(s):" +for endpoint in "${API_ENDPOINTS[@]}"; do + echo " • $endpoint" +done +echo "" + +# Check CLI coverage +echo "🔍 Checking CLI coverage..." +echo "" + +# Extract CLI commands from gantt.sh (or similar unified CLI) +CLI_FILE="${SCRIPT_DIR}/gantt.sh" +if [ ! -f "$CLI_FILE" ]; then + log_warn "Unified CLI not found at $CLI_FILE" + log_info "Checking for individual scripts..." + + # Look for any shell scripts + CLI_SCRIPTS=($(find "$SCRIPT_DIR" -name "*.sh" -type f ! -name "audit-cli-coverage.sh" | sort)) + + if [ ${#CLI_SCRIPTS[@]} -eq 0 ]; then + log_error "No CLI scripts found!" + exit 1 + fi + + echo "Found CLI scripts:" + for script in "${CLI_SCRIPTS[@]}"; do + echo " • $(basename "$script")" + done +fi + +# Compare API to CLI coverage +echo "" +echo "═══════════════════════════════════════════════════════════" +echo " Coverage Report" +echo "═══════════════════════════════════════════════════════════" +echo "" + +# This is project-specific - customize based on your CLI structure +# For gantt-board, we check against known CLI commands + +declare -A CLI_MAP=( + ["GET /api/tasks"]='task list' + ["POST /api/tasks"]='task create' + ["DELETE /api/tasks"]='task delete' + ["POST /api/tasks/natural"]='task natural' +) + +MISSING=0 +COVERED=0 + +for endpoint in "${API_ENDPOINTS[@]}"; do + if [ -n "${CLI_MAP[$endpoint]}" ]; then + log_info "$endpoint → ${CLI_MAP[$endpoint]}" + ((COVERED++)) + else + log_error "$endpoint → NO CLI COMMAND" + ((MISSING++)) + fi +done + +echo "" +echo "═══════════════════════════════════════════════════════════" +echo " Summary" +echo "═══════════════════════════════════════════════════════════" +echo "" + +if [ $MISSING -eq 0 ]; then + log_info "All API endpoints have CLI coverage!" + echo "" + echo " Total endpoints: ${#API_ENDPOINTS[@]}" + echo " Covered: $COVERED" + echo " Missing: $MISSING" + echo "" + exit 0 +else + log_error "CLI coverage incomplete!" + echo "" + echo " Total endpoints: ${#API_ENDPOINTS[@]}" + echo " Covered: $COVERED" + echo " Missing: $MISSING" + echo "" + echo "Add CLI commands for missing endpoints before committing." + echo "See Rule 2.5 in MEMORY.md for details." + echo "" + exit 1 +fi