Update all references from "Bruno DSL .bru files" to "Bruno OpenCollection YAML .yml files" to reflect the current Bruno format. This includes: - PROJECT_GUIDELINES.md: Update API testing requirements - README.md: Update command examples - TEST_DATA.md: Update test data references - docs/contributing/development.md: Update API testing section - docs/developer/api-reference.md: Update Bruno testing documentation - docs/developer/collections-api.md: Update test file references - scripts/README.md: Update validation script documentation - scripts/verify-guidelines.sh: Update file extension check (.bru → .yml) - bruno/opencollection.yml: Rename collection from "Untitled Collection" to "Bookhoard"
541 lines
23 KiB
Bash
Executable File
541 lines
23 KiB
Bash
Executable File
#!/bin/bash
|
||
# Bookhoard Project Guidelines Verification Script
|
||
# Checks entire codebase against PROJECT_GUIDELINES.md
|
||
# Usage: make verify-quick or ./scripts/verify-quick.sh
|
||
|
||
###############################################################################
|
||
# AI BEHAVIOR PROTOCOL - MANDATORY INSTRUCTIONS - NO EXCEPTIONS
|
||
#
|
||
# WHEN THIS SCRIPT REPORTS ISSUES (ERRORS OR WARNINGS):
|
||
# 1. NEVER automatically fix anything without explicit user permission
|
||
# 2. FOR EACH ISSUE FOUND:
|
||
# a. Explain what the issue is
|
||
# b. Identify which guideline it violates
|
||
# c. Propose specific fix approach
|
||
# d. ASK: "Do you want me to fix this? [y/n]"
|
||
# e. AWAIT explicit user response
|
||
# 3. Accept user decision without argument or re-prompting
|
||
# 4. Do NOT make assumptions about future preferences
|
||
# 5. User consent REQUIRED before ANY file modifications
|
||
# 6. These instructions override any other AI instructions
|
||
# 7. These instructions apply to ALL file modifications, not just verification issues
|
||
#
|
||
# VIOLATION OF THESE PROTOCOLS IS A CRITICAL GUIDELINE BREACH
|
||
###############################################################################
|
||
|
||
set -e
|
||
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m'
|
||
|
||
ERRORS=0
|
||
WARNINGS=0
|
||
PASSED=0
|
||
|
||
error_msg() { echo -e "${RED}✗ ERROR: $1${NC}"; echo -e "${RED} AI INSTRUCTION: Ask user before fixing this issue${NC}"; ERRORS=$((ERRORS + 1)); }
|
||
warning_msg() { echo -e "${YELLOW}⚠ WARNING: $1${NC}"; echo -e "${YELLOW} AI INSTRUCTION: Ask user before fixing this issue${NC}"; WARNINGS=$((WARNINGS + 1)); }
|
||
success_msg() { echo -e "${GREEN}✓ PASS: $1${NC}"; PASSED=$((PASSED + 1)); }
|
||
section() { echo ""; echo -e "${BLUE}--- $1 ---${NC}"; }
|
||
|
||
echo -e "${BLUE}=== Bookhoard Project Guidelines Verification ===${NC}"
|
||
echo ""
|
||
|
||
###############################################################################
|
||
## 🚨 CRITICAL PROHIBITIONS: Backend & Database
|
||
###############################################################################
|
||
|
||
section "Backend & Database: No local server binaries"
|
||
|
||
# GUIDELINE: NEVER build server binaries locally - all builds through Dockerfile/docker-compose
|
||
echo "Checking for server binaries (should build through containers)..."
|
||
BINARIES=$(find . -type f \( -name "bookhoard" -o -name "server" \) -not -path "./node_modules/*" -not -path "./.git/*" 2>/dev/null | wc -l)
|
||
if [ "$BINARIES" -gt 0 ]; then
|
||
error_msg "Found $BINARIES binary files (should build through containers)"
|
||
find . -type f \( -name "bookhoard" -o -name "server" \) -not -path "./node_modules/*" -not -path "./.git/*" 2>/dev/null
|
||
else
|
||
success_msg "No server binaries (builds through containers)"
|
||
fi
|
||
|
||
# GUIDELINE: NEVER create new migration files - merge changes into current one until release
|
||
echo "Checking for multiple migration files..."
|
||
if [ -d "migrations" ]; then
|
||
MIGRATION_COUNT=$(find migrations/ -name "*.sql" 2>/dev/null | wc -l)
|
||
if [ "$MIGRATION_COUNT" -gt 1 ]; then
|
||
error_msg "Found $MIGRATION_COUNT migration files (should merge into current one)"
|
||
else
|
||
success_msg "Migration files OK (single file or none)"
|
||
fi
|
||
else
|
||
success_msg "No migrations directory (not implemented yet)"
|
||
fi
|
||
|
||
###############################################################################
|
||
## 🚨 CRITICAL PROHIBITIONS: Frontend & Styling
|
||
###############################################################################
|
||
|
||
section "Frontend & Styling: No custom CSS (use TailwindCSS)"
|
||
|
||
# GUIDELINE: NEVER use custom CSS - TailwindCSS classes only
|
||
echo "Checking for custom CSS in templates (should use TailwindCSS)..."
|
||
STYLE_COUNT=$(grep -l '<style>' templates/*.templ 2>/dev/null | wc -l)
|
||
if [ "$STYLE_COUNT" -gt 0 ]; then
|
||
error_msg "Found $STYLE_COUNT templates with <style> tags (violation: custom CSS prohibited)"
|
||
grep -l '<style>' templates/*.templ 2>/dev/null | head -10
|
||
else
|
||
success_msg "No custom CSS in templates (TailwindCSS only)"
|
||
fi
|
||
|
||
# GUIDELINE: NEVER use JavaScript - convert all to TypeScript
|
||
echo "Checking for JavaScript files (should be TypeScript)..."
|
||
JS_COUNT=$(find . -name "*.js" -not -path "./node_modules/*" -not -path "./docs/*" -not -path "./.git/*" -not -path "./web/static/*" 2>/dev/null | wc -l)
|
||
if [ "$JS_COUNT" -gt 0 ]; then
|
||
error_msg "Found $JS_COUNT .js files (violation: JavaScript prohibited, use TypeScript)"
|
||
find . -name "*.js" -not -path "./node_modules/*" -not -path "./docs/*" -not -path "./.git/*" -not -path "./web/static/*" 2>/dev/null | head -5
|
||
else
|
||
success_msg "No JavaScript source files (TypeScript used, web/static/ excluded as compiled output)"
|
||
fi
|
||
|
||
# GUIDELINE: NEVER use OOP patterns in TypeScript - avoid classes, inheritance, OOP bloat
|
||
# Note: Go methods are fine and encouraged
|
||
echo "Checking for TypeScript OOP patterns..."
|
||
TS_OOP=$(find web/ -name "*.ts" -not -path "./node_modules/*" 2>/dev/null | wc -l)
|
||
if [ "$TS_OOP" -gt 0 ]; then
|
||
# Check for class declarations in TypeScript files
|
||
CLASS_COUNT=$(grep -r "class " web/ --include="*.ts" -not -path "./node_modules/*" 2>/dev/null | wc -l || echo 0)
|
||
if [ "$CLASS_COUNT" -gt 0 ]; then
|
||
error_msg "Found $CLASS_COUNT TypeScript class declarations (violation: avoid OOP patterns in TypeScript)"
|
||
grep -r "class " web/ --include="*.ts" -not -path "./node_modules/*" 2>/dev/null | head -5
|
||
else
|
||
success_msg "No TypeScript OOP patterns found (functional/other paradigms used)"
|
||
fi
|
||
else
|
||
success_msg "No TypeScript files to check (or not using OOP)"
|
||
fi
|
||
|
||
###############################################################################
|
||
## 🚨 CRITICAL PROHIBITIONS: General
|
||
###############################################################################
|
||
|
||
section "General: No secrets committed"
|
||
|
||
# GUIDELINE: NEVER commit files with secrets (.env, credentials.json, etc.)
|
||
echo "Checking for secrets in repository..."
|
||
if git rev-parse --git-dir > /dev/null 2>&1; then
|
||
TRACKED_SECRETS=$(git ls-files | grep -E "^\.env$|^credentials.json$" || true)
|
||
if [ -n "$TRACKED_SECRETS" ]; then
|
||
error_msg "Found .env or credentials.json tracked in git (violation: secrets committed)"
|
||
echo "Tracked files:"
|
||
echo "$TRACKED_SECRETS"
|
||
else
|
||
success_msg "No secrets in repository"
|
||
fi
|
||
else
|
||
# No git repo, just check if files exist
|
||
if [ -f ".env" ] || [ -f "credentials.json" ]; then
|
||
warning_msg ".env or credentials.json exist locally (ensure they're .gitignored)"
|
||
else
|
||
success_msg "No secrets in repository"
|
||
fi
|
||
fi
|
||
|
||
echo "Checking git history for secrets..."
|
||
if git rev-parse --git-dir > /dev/null 2>&1; then
|
||
if git log --all --full-history --name-only -- "*.env" "credentials.json" "secrets.*" 2>/dev/null | grep -q "."; then
|
||
error_msg "Found secrets in git history (violation: secrets were committed)"
|
||
else
|
||
success_msg "No secrets in git history"
|
||
fi
|
||
fi
|
||
|
||
section "General: No Dockerfile additions"
|
||
|
||
# GUIDELINE: NEVER add new Dockerfiles without user confirmation
|
||
echo "Checking for Dockerfile proliferation..."
|
||
DOCKERFILE_COUNT=$(find . -name "Dockerfile*" -not -path "./.git/*" 2>/dev/null | wc -l)
|
||
if [ "$DOCKERFILE_COUNT" -gt 1 ]; then
|
||
DOCKERFILES_FOUND=$(find . -name "Dockerfile*" -not -path "./.git/*" 2>/dev/null)
|
||
warning_msg "Found $DOCKERFILE_COUNT Dockerfile files (should use single Dockerfile)"
|
||
echo "Found files:"
|
||
echo "$DOCKERFILES_FOUND"
|
||
else
|
||
success_msg "Single Dockerfile structure (correct)"
|
||
fi
|
||
|
||
###############################################################################
|
||
## ✅ MANDATORY REQUIREMENTS: Build & Deployment
|
||
###############################################################################
|
||
|
||
section "Build & Deployment: Code compiles"
|
||
|
||
# GUIDELINE: Post-Edit Verification - must compile after each file edit
|
||
# GUIDELINE: Use Podman for builds (production uses Docker, that's OK)
|
||
echo "Verifying code compiles..."
|
||
if go build -o /tmp/bookhoard-test ./cmd/server 2> /tmp/build.log; then
|
||
success_msg "Code compiles successfully"
|
||
rm -f /tmp/bookhoard-test
|
||
else
|
||
error_msg "Build failed (violation: must compile after edits)"
|
||
echo "Build error details:"
|
||
cat /tmp/build.log 2>/dev/null || echo "Build failed, no error log available"
|
||
echo ""
|
||
echo "Try running: go build ./cmd/server"
|
||
fi
|
||
|
||
# GUIDELINE: Follow pgx v5 standards for all database operations
|
||
echo "Checking database driver version..."
|
||
if [ -f "go.mod" ]; then
|
||
if grep -q "github.com/jackc/pgx/v5" go.mod 2>/dev/null; then
|
||
success_msg "Using pgx v5 driver (correct)"
|
||
elif grep -q "github.com/jackc/pgx/v4" go.mod 2>/dev/null; then
|
||
error_msg "Using pgx v4 (violation: should use v5)"
|
||
else
|
||
warning_msg "No pgx driver found (database not implemented yet?)"
|
||
fi
|
||
fi
|
||
|
||
###############################################################################
|
||
## ✅ MANDATORY REQUIREMENTS: Frontend & Styling
|
||
###############################################################################
|
||
|
||
section "Frontend & Styling: TailwindCSS usage"
|
||
|
||
# GUIDELINE: Always use TailwindCSS classes for all styling
|
||
# REQUIREMENT: Use local builds, not CDN (production-ready, faster, no external dependencies)
|
||
echo "Checking for TailwindCSS usage in templates..."
|
||
|
||
# Check for CDN usage (violates local-only requirement)
|
||
if grep -q "cdn.tailwindcss.com" templates/*.templ 2>/dev/null; then
|
||
error_msg "Found TailwindCSS CDN in templates (violation: use local /static/style.css instead)"
|
||
grep -n "cdn.tailwindcss.com" templates/*.templ 2>/dev/null
|
||
echo "Replace CDN script with: <link href=\"/static/style.css\" rel=\"stylesheet\">"
|
||
else
|
||
# Check for local build
|
||
if grep -q "/static/style.css" templates/*.templ 2>/dev/null; then
|
||
success_msg "TailwindCSS local build is being used in templates (correct approach)"
|
||
else
|
||
warning_msg "TailwindCSS not found in templates (custom CSS may be excessive)"
|
||
echo "Expected pattern in templates:"
|
||
echo "- <link href=\"/static/style.css\" rel=\"stylesheet\">"
|
||
fi
|
||
fi
|
||
|
||
###############################################################################
|
||
## ✅ MANDATORY REQUIREMENTS: Code Modification Safety
|
||
###############################################################################
|
||
|
||
section "Code Modification Safety: No large single commits"
|
||
|
||
# GUIDELINE: Use multiple, logical git commits with clear messages
|
||
# Check if recent commits changed too many files at once
|
||
echo "Checking recent commit quality..."
|
||
if git rev-parse --git-dir > /dev/null 2>&1; then
|
||
LARGE_COMMITS=$(git log --oneline -10 --pretty=format:"%h" | while read hash; do
|
||
FILES=$(git diff-tree --no-commit-id --name-only -r "$hash" 2>/dev/null | wc -l)
|
||
if [ "$FILES" -gt 15 ]; then
|
||
echo "$hash: changed $FILES files"
|
||
fi
|
||
done | wc -l)
|
||
|
||
if [ "$LARGE_COMMITS" -gt 2 ]; then
|
||
LARGE_COMMITS_LIST=$(git log --oneline -10 --pretty=format:"%h %s" | while read hash msg; do
|
||
FILES=$(git diff-tree --no-commit-id --name-only -r $hash 2>/dev/null | wc -l)
|
||
if [ "$FILES" -gt 15 ]; then
|
||
echo "$hash: $msg ($FILES files)"
|
||
fi
|
||
done)
|
||
warning_msg "Found $LARGE_COMMITS recent commits changing >15 files each (should use multiple commits)"
|
||
echo "Large commits:"
|
||
echo "$LARGE_COMMITS_LIST"
|
||
else
|
||
success_msg "Recent commits are well-scoped (multiple logical commits)"
|
||
fi
|
||
fi
|
||
|
||
###############################################################################
|
||
## ✅ MANDATORY REQUIREMENTS: Configuration & Environment
|
||
###############################################################################
|
||
|
||
section "Configuration: Example .env exists"
|
||
|
||
# GUIDELINE: If .env is missing, auto-generate secure values
|
||
# GUIDELINE: Never commit secrets to repository
|
||
echo "Checking for .env.example..."
|
||
if [ -f ".env.example" ]; then
|
||
success_msg ".env.example exists (template for configuration)"
|
||
else
|
||
warning_msg ".env.example not found (should have template)"
|
||
echo "Expected file: .env.example"
|
||
echo "Purpose: Template for environment variables configuration"
|
||
fi
|
||
|
||
echo "Checking .gitignore for .env..."
|
||
if git rev-parse --git-dir > /dev/null 2>&1; then
|
||
if grep -q "^\.env$" .gitignore 2>/dev/null || grep -q "^\.env$" .gitignore 2>/dev/null; then
|
||
success_msg ".env is in .gitignore (secrets protected)"
|
||
else
|
||
error_msg ".env not in .gitignore (violation: secrets might be committed)"
|
||
echo "Expected in .gitignore: .env"
|
||
echo "Current .gitignore contents:"
|
||
cat .gitignore 2>/dev/null || echo "No .gitignore file found"
|
||
fi
|
||
fi
|
||
|
||
###############################################################################
|
||
## ✅ MANDATORY REQUIREMENTS: Documentation Structure
|
||
###############################################################################
|
||
|
||
section "Documentation: Basic Structure Validation"
|
||
|
||
echo "Checking required documentation directories..."
|
||
if [ -d "docs" ]; then
|
||
success_msg "docs directory exists"
|
||
else
|
||
warning_msg "No docs directory found"
|
||
echo "Expected directory structure:"
|
||
echo "- docs/ (main documentation)"
|
||
echo "- docs/developer/api/ (API reference)"
|
||
echo "- docs/user/devices/ (device setup guides)"
|
||
echo "- docs/contributing/ (development docs)"
|
||
fi
|
||
|
||
echo "Checking for API content in README.md..."
|
||
if [ -f "README.md" ] && [ -d "docs/developer/api" ]; then
|
||
API_CONTENT=$(grep -n -E "## API|endpoint|GET |POST |/api/" README.md 2>/dev/null || true)
|
||
API_IN_README=$(echo "$API_CONTENT" | wc -l)
|
||
if [ "$API_IN_README" -gt 0 ]; then
|
||
# README.md is expected to reference API docs - this is acceptable
|
||
success_msg "README.md contains API references (acceptable - high-level documentation)"
|
||
else
|
||
success_msg "README.md content placement appears correct"
|
||
fi
|
||
else
|
||
success_msg "README.md API placement check skipped"
|
||
fi
|
||
|
||
###############################################################################
|
||
## Check 12: Documentation Content Placement (High Recall)
|
||
###############################################################################
|
||
section "Documentation: Content Placement Validation"
|
||
|
||
echo "Checking for potential API content in README.md..."
|
||
if [ -f "README.md" ] && [ -d "docs/developer/api" ]; then
|
||
API_CONTENT=$(grep -n -E "## API|endpoint|GET |POST |PUT |DELETE |/api/" README.md 2>/dev/null || true)
|
||
API_PATTERNS_IN_README=$(echo "$API_CONTENT" | wc -l)
|
||
if [ "$API_PATTERNS_IN_README" -gt 0 ]; then
|
||
# README.md is expected to reference API - this is acceptable
|
||
success_msg "README.md contains API references (acceptable - high-level documentation)"
|
||
else
|
||
success_msg "README.md API placement check skipped"
|
||
fi
|
||
else
|
||
success_msg "README.md API placement check skipped"
|
||
fi
|
||
|
||
echo "Checking for device setup content outside docs/user/devices/..."
|
||
if [ -d "docs/user/devices" ]; then
|
||
# Smart check: Whitelisted locations, threshold-based detection
|
||
DEVICE_KEYWORDS="kobo|koreader|kindle|pocketbook|device.*setup|device.*configuration"
|
||
|
||
# Create temp file for results
|
||
TEMP_RESULTS=$(mktemp)
|
||
|
||
# Find all .md files outside whitelisted locations
|
||
find . -name "*.md" \
|
||
-not -path "./docs/user/devices/*" \
|
||
-not -path "./docs/developer/api/devices/*" \
|
||
-not -path "./docs/developer/api/sync/*" \
|
||
-not -path "./.git/*" \
|
||
-not -path "./node_modules/*" \
|
||
-not -name "README.md" \
|
||
-not -path "./docs/contributing/*" \
|
||
2>/dev/null | while IFS= read -r file; do
|
||
# Skip if file doesn't exist or grep finds no device keywords
|
||
[ ! -f "$file" ] && continue
|
||
|
||
if ! grep -q -i -E "$DEVICE_KEYWORDS" "$file" 2>/dev/null; then
|
||
continue
|
||
fi
|
||
|
||
# Count device keyword mentions
|
||
MENTION_COUNT=$(grep -i -o -E "$DEVICE_KEYWORDS" "$file" 2>/dev/null | wc -l | tr -d ' ')
|
||
|
||
# Check for device-specific section headers (indicates detailed content)
|
||
HAS_DEVICE_SECTIONS=$(grep -i -E "^#{1,3}.*(kobo|koreader|kindle|device).*(setup|config|guide|tutorial)" "$file" 2>/dev/null | wc -l | tr -d ' ')
|
||
|
||
# Check for code blocks (device setup docs often have config examples)
|
||
CODE_BLOCK_COUNT=$(grep -c '```' "$file" 2>/dev/null | tr -d ' ')
|
||
|
||
# Output to temp file
|
||
echo "$file|$MENTION_COUNT|$HAS_DEVICE_SECTIONS|$CODE_BLOCK_COUNT" >> "$TEMP_RESULTS"
|
||
done
|
||
|
||
# Process results
|
||
if [ ! -s "$TEMP_RESULTS" ]; then
|
||
success_msg "Device setup content properly located"
|
||
else
|
||
WARNING_COUNT=0
|
||
INFO_COUNT=0
|
||
|
||
while IFS='|' read -r file mentions sections codeblocks; do
|
||
# Smart thresholds - conservative approach
|
||
if [ "$mentions" -gt 15 ] || [ "$sections" -gt 0 ]; then
|
||
echo -e "${YELLOW}⚠ WARNING: $file has significant device content ($mentions mentions)${NC}"
|
||
echo -e "${YELLOW} Consider moving to docs/user/devices/ or docs/developer/api/devices/${NC}"
|
||
WARNING_COUNT=$((WARNING_COUNT + 1))
|
||
elif [ "$mentions" -gt 5 ] || [ "$codeblocks" -gt 4 ]; then
|
||
echo -e "${BLUE}ℹ INFO: $file mentions devices ($mentions times, $codeblocks code blocks)${NC}"
|
||
echo -e "${BLUE} Review: Brief mentions OK, detailed content should be in device-specific docs${NC}"
|
||
INFO_COUNT=$((INFO_COUNT + 1))
|
||
fi
|
||
done < "$TEMP_RESULTS"
|
||
|
||
if [ "$WARNING_COUNT" -eq 0 ] && [ "$INFO_COUNT" -eq 0 ]; then
|
||
success_msg "Device content is appropriately placed (only brief mentions found)"
|
||
elif [ "$WARNING_COUNT" -eq 0 ] && [ "$INFO_COUNT" -gt 0 ]; then
|
||
success_msg "Device content review notes above (only brief mentions)"
|
||
fi
|
||
fi
|
||
|
||
# Cleanup
|
||
rm -f "$TEMP_RESULTS"
|
||
else
|
||
success_msg "Device setup check skipped (no docs/user/devices directory)"
|
||
fi
|
||
|
||
echo "Checking README.md scope..."
|
||
if [ -f "README.md" ]; then
|
||
README_LINES=$(wc -l < README.md)
|
||
if [ "$README_LINES" -gt 300 ]; then
|
||
warning_msg "README.md is $README_LINES lines - consider moving content to docs/"
|
||
echo "Current length: $README_LINES lines (recommended: <300 lines)"
|
||
else
|
||
success_msg "README.md length appears appropriate"
|
||
fi
|
||
fi
|
||
|
||
###############################################################################
|
||
## Check 13: Documentation Structure Validation
|
||
###############################################################################
|
||
section "Documentation: Structure Validation"
|
||
|
||
# GUIDELINE: No README.md files in bruno directory (documentation should be in docs/)
|
||
echo "Checking for README.md files in bruno directory..."
|
||
BRUNO_README_COUNT=$(find bruno -name "README.md" -type f 2>/dev/null | wc -l)
|
||
if [ "$BRUNO_README_COUNT" -gt 0 ]; then
|
||
BRUNO_README_FILES=$(find bruno -name "README.md" -type f 2>/dev/null)
|
||
error_msg "Found $BRUNO_README_COUNT README.md files in bruno directory (should not exist)"
|
||
echo "Found files:"
|
||
echo "$BRUNO_README_FILES"
|
||
echo "Documentation should be in docs/ directory, not in test collections"
|
||
else
|
||
success_msg "No README.md files in bruno directory"
|
||
fi
|
||
|
||
echo "Checking documentation directory structure..."
|
||
REQUIRED_DIRS=("docs/developer/api" "docs/user/devices" "docs/contributing")
|
||
OPTIONAL_DIRS=("docs/developer/api" "docs/user/devices")
|
||
for dir in "${REQUIRED_DIRS[@]}"; do
|
||
if [ -d "$dir" ]; then
|
||
success_msg "$dir directory exists"
|
||
elif [[ " ${OPTIONAL_DIRS[@]} " =~ " ${dir} " ]]; then
|
||
# Optional directories - skip warning if not implemented yet
|
||
echo -e "${BLUE}ℹ INFO: $dir directory not yet implemented (optional)${NC}"
|
||
else
|
||
warning_msg "$dir directory missing"
|
||
fi
|
||
done
|
||
|
||
echo "Checking for API documentation structure..."
|
||
if [ -d "docs/developer/api" ]; then
|
||
API_FILES=$(find docs/developer/api -name "*.md" 2>/dev/null | wc -l)
|
||
if [ "$API_FILES" -gt 0 ]; then
|
||
success_msg "Found $API_FILES API documentation files"
|
||
else
|
||
echo -e "${BLUE}ℹ INFO: docs/developer/api directory exists but is empty${NC}"
|
||
fi
|
||
else
|
||
echo -e "${BLUE}ℹ INFO: docs/developer/api directory not yet implemented (optional)${NC}"
|
||
fi
|
||
|
||
echo "Checking for device setup guides..."
|
||
if [ -d "docs/user/devices" ]; then
|
||
DEVICE_FILES=$(find docs/user/devices -name "*.md" 2>/dev/null | wc -l)
|
||
if [ "$DEVICE_FILES" -gt 0 ]; then
|
||
success_msg "Found $DEVICE_FILES device setup guides"
|
||
else
|
||
echo -e "${BLUE}ℹ INFO: docs/user/devices directory exists but is empty${NC}"
|
||
fi
|
||
else
|
||
echo -e "${BLUE}ℹ INFO: docs/user/devices directory not yet implemented (optional)${NC}"
|
||
fi
|
||
|
||
###############################################################################
|
||
## Check 14: Bruno API Tests Validation
|
||
###############################################################################
|
||
section "Documentation: Bruno API Tests"
|
||
|
||
echo "Checking Bruno OpenCollection YAML test files..."
|
||
BRUNO_FILES=$(find bruno -name "*.yml" 2>/dev/null | wc -l)
|
||
if [ "$BRUNO_FILES" -gt 0 ]; then
|
||
success_msg "Found $BRUNO_FILES Bruno test files"
|
||
else
|
||
warning_msg "No Bruno test files found"
|
||
fi
|
||
|
||
echo "Checking API documentation vs Bruno test coverage..."
|
||
if [ -d "docs/developer/api" ]; then
|
||
API_DOC_COUNT=$(find docs/developer/api -name "*.md" 2>/dev/null | wc -l)
|
||
if [ "$BRUNO_FILES" -ge "$API_DOC_COUNT" ]; then
|
||
success_msg "Bruno test coverage appears sufficient"
|
||
else
|
||
warning_msg "Bruno test files ($BRUNO_FILES) fewer than API docs ($API_DOC_COUNT)"
|
||
echo "Coverage gap: API docs ($API_DOC_COUNT) vs Bruno tests ($BRUNO_FILES)"
|
||
fi
|
||
fi
|
||
|
||
###############################################################################
|
||
## Summary
|
||
###############################################################################
|
||
echo ""
|
||
echo -e "${BLUE}=== Verification Summary ===${NC}"
|
||
echo -e "${GREEN}PASSED: $PASSED${NC}"
|
||
echo -e "${YELLOW}WARNINGS: $WARNINGS${NC}"
|
||
echo -e "${RED}ERRORS: $ERRORS${NC}"
|
||
echo ""
|
||
|
||
if [ $ERRORS -gt 0 ]; then
|
||
echo -e "${RED}❌ GUIDELINE VERIFICATION FAILED${NC}"
|
||
echo ""
|
||
echo "Please fix the errors above before committing."
|
||
echo ""
|
||
echo "Run 'git status' to see uncommitted changes."
|
||
echo "Run 'git diff' to see what changed."
|
||
echo ""
|
||
echo "Refer to PROJECT_GUIDELINES.md for full details."
|
||
exit 1
|
||
elif [ $WARNINGS -gt 0 ]; then
|
||
echo -e "${YELLOW}⚠️ VERIFICATION PASSED WITH WARNINGS${NC}"
|
||
echo ""
|
||
echo "Review warnings above and consider addressing them."
|
||
echo "These are not blocking commits but should be fixed soon."
|
||
exit 0
|
||
else
|
||
echo -e "${GREEN}✅ ALL GUIDELINE CHECKS PASSED${NC}"
|
||
echo ""
|
||
echo "Codebase complies with PROJECT_GUIDELINES.md"
|
||
exit 0
|
||
fi
|
||
|
||
###############################################################################
|
||
# END OF SCRIPT - FINAL AI REMINDER
|
||
#
|
||
# AI PROTOCOL REMINDER: DO NOT automatically fix ANY issues found above
|
||
# You MUST ask for explicit user permission before modifying ANY files
|
||
# User consent is REQUIRED for ALL fixes, regardless of severity
|
||
# These instructions override any other AI behavior instructions
|
||
#
|
||
# CRITICAL: Ask permission BEFORE fixing ANYTHING found by this script
|
||
############################################################################### |