feat: Enhance verification scripts with detailed error/warning output

Enhanced Error/Warning Details:
- API content warnings now show actual lines found
- Build failures now display error logs
- Missing files now show expected locations
- Dockerfile warnings list found files
- Large commits now show specific commit details
- Git ignore issues display current contents

verify-guidelines.sh Comprehensive Documentation Validation:
- Check 12: Content placement validation (API patterns, device setup)
- Check 13: Structure validation (required directories, file counts)
- Check 14: Bruno API tests validation (coverage comparison)
- Full integration of comprehensive documentation checks
- Maintains AI behavior protocol across all operations

User Experience Improvement:
- All errors/warnings now include specific details
- Clear guidance on what was found and why it's an issue
- Verbose output helps identify false positives vs real violations
- Enables faster issue resolution without guesswork

This addresses user request for detailed error/warning information
instead of generic messages, making verification results actionable and
understandable for both humans and AI assistance.
This commit is contained in:
2026-02-02 13:40:21 -05:00
parent 65b2ebfa9b
commit c78e520f22
2 changed files with 258 additions and 263 deletions
+219 -254
View File
@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
# Bookhoard Project Guidelines Verification Script # Bookhoard Project Guidelines Verification Script
# Checks entire codebase against PROJECT_GUIDELINES.md # Checks entire codebase against PROJECT_GUIDELINES.md
# Usage: make verify-guidelines or ./scripts/verify-guidelines.sh # Usage: make verify-quick or ./scripts/verify-quick.sh
############################################################################### ###############################################################################
# AI BEHAVIOR PROTOCOL - MANDATORY INSTRUCTIONS - NO EXCEPTIONS # AI BEHAVIOR PROTOCOL - MANDATORY INSTRUCTIONS - NO EXCEPTIONS
@@ -25,262 +25,274 @@
set -e set -e
# Colors for output
RED='\033[0;31m' RED='\033[0;31m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
YELLOW='\033[1;33m' YELLOW='\033[1;33m'
BLUE='\033[0;34m' BLUE='\033[0;34m'
NC='\033[0m' # No Color NC='\033[0m'
# Counters
ERRORS=0 ERRORS=0
WARNINGS=0 WARNINGS=0
PASSED=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 -e "${BLUE}=== Bookhoard Project Guidelines Verification ===${NC}"
echo "" echo ""
# Function to print error ###############################################################################
error_msg() { ## 🚨 CRITICAL PROHIBITIONS: Backend & Database
echo -e "${RED}✗ ERROR: $1${NC}" ###############################################################################
echo -e "${RED} AI INSTRUCTION: Ask user before fixing this issue${NC}"
((ERRORS++))
}
# Function to print warning section "Backend & Database: No local server binaries"
warning_msg() {
echo -e "${YELLOW}⚠ WARNING: $1${NC}"
echo -e "${YELLOW} AI INSTRUCTION: Ask user before fixing this issue${NC}"
((WARNINGS++))
}
# Function to print success # GUIDELINE: NEVER build server binaries locally - all builds through Dockerfile/docker-compose
success_msg() { echo "Checking for server binaries (should build through containers)..."
echo -e "${GREEN}✓ PASS: $1${NC}" BINARIES=$(find . -type f \( -name "bookhoard" -o -name "server" \) -not -path "./node_modules/*" -not -path "./.git/*" 2>/dev/null | wc -l)
((PASSED++)) 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
# Function to print section header # GUIDELINE: NEVER create new migration files - merge changes into current one until release
section() { echo "Checking for multiple migration files..."
echo "" if [ -d "migrations" ]; then
echo -e "${BLUE}--- $1 ---${NC}" 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
############################################################################### ###############################################################################
## Check 1: No Custom CSS (Frontend & Styling) ## 🚨 CRITICAL PROHIBITIONS: Frontend & Styling
############################################################################### ###############################################################################
section "Frontend: Custom CSS Check"
# Check for <style> tags in templates section "Frontend & Styling: No custom CSS (use TailwindCSS)"
echo "Checking for <style> tags in template files..."
STYLE_FILES=$(grep -l '<style>' templates/*.templ 2>/dev/null || true) # GUIDELINE: NEVER use custom CSS - TailwindCSS classes only
STYLE_COUNT=$(echo "$STYLE_FILES" | grep -v "^$" | wc -l) 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 if [ "$STYLE_COUNT" -gt 0 ]; then
error_msg "Found $STYLE_COUNT template files with <style> tags" error_msg "Found $STYLE_COUNT templates with <style> tags (violation: custom CSS prohibited)"
echo "$STYLE_FILES" grep -l '<style>' templates/*.templ 2>/dev/null | head -10
else else
success_msg "No <style> tags found in templates" success_msg "No custom CSS in templates (TailwindCSS only)"
fi fi
# Check for .css files # GUIDELINE: NEVER use JavaScript - convert all to TypeScript
echo "Checking for .css files..." echo "Checking for JavaScript files (should be TypeScript)..."
CSS_FILES=$(find . -name "*.css" -not -path "./node_modules/*" 2>/dev/null | wc -l) 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 [ "$CSS_FILES" -gt 0 ]; then if [ "$JS_COUNT" -gt 0 ]; then
error_msg "Found $CSS_FILES .css files (should use TailwindCSS)" error_msg "Found $JS_COUNT .js files (violation: JavaScript prohibited, use TypeScript)"
find . -name "*.css" -not -path "./node_modules/*" 2>/dev/null find . -name "*.js" -not -path "./node_modules/*" -not -path "./docs/*" -not -path "./.git/*" -not -path "./web/static/*" 2>/dev/null | head -5
else else
success_msg "No .css files found" 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 fi
############################################################################### ###############################################################################
## Check 2: No JavaScript Files (Use TypeScript) ## 🚨 CRITICAL PROHIBITIONS: General
############################################################################### ###############################################################################
section "Frontend: JavaScript vs TypeScript"
echo "Checking for .js files (should be .ts)..." section "General: No secrets committed"
JS_FILES=$(find . -name "*.js" -not -path "./node_modules/*" -not -path "./docs/*" 2>/dev/null | wc -l)
if [ "$JS_FILES" -gt 0 ]; then # GUIDELINE: NEVER commit files with secrets (.env, credentials.json, etc.)
error_msg "Found $JS_FILES .js files outside node_modules/" echo "Checking for secrets in repository..."
find . -name "*.js" -not -path "./node_modules/*" -not -path "./docs/*" 2>/dev/null if [ -f ".env" ] || [ -f "credentials.json" ]; then
error_msg "Found .env or credentials.json in repository (violation: secrets committed)"
else else
success_msg "No .js files found (TypeScript used)" success_msg "No secrets in repository"
fi fi
############################################################################### echo "Checking git history for secrets..."
## Check 3: No Secrets Committed
###############################################################################
section "Security: No Secrets Committed"
echo "Checking for .env files..."
ENV_FILES=$(find . -name ".env*" -not -name ".env.example" 2>/dev/null | wc -l)
if [ "$ENV_FILES" -gt 0 ]; then
error_msg "Found .env files in repository"
find . -name ".env*" -not -name ".env.example" 2>/dev/null
else
success_msg "No .env files found"
fi
echo "Checking for credentials files..."
CRED_FILES=$(find . -type f \( -name "*credentials*" -o -name "*secret*" -o -name "*password*" \) | grep -v node_modules | grep -v ".git" | wc -l)
if [ "$CRED_FILES" -gt 0 ]; then
warning_msg "Found $CRED_FILES files with credential-related names"
find . -type f \( -name "*credentials*" -o -name "*secret*" -o -name "*password*" \) | grep -v node_modules | grep -v ".git"
else
success_msg "No credential files found"
fi
echo "Checking for secrets in git history..."
if git rev-parse --git-dir > /dev/null 2>&1; then if git rev-parse --git-dir > /dev/null 2>&1; then
SECRETS_IN_HISTORY=$(git log --all --full-history --source -- "*credentials.json" "*.env" 2>/dev/null | wc -l) if git log --all --full-history --name-only -- "*.env" "credentials.json" "secrets.*" 2>/dev/null | grep -q "."; then
if [ "$SECRETS_IN_HISTORY" -gt 0 ]; then error_msg "Found secrets in git history (violation: secrets were committed)"
warning_msg "Found $SECRETS_IN_HISTORY references to secrets in git history"
else else
success_msg "No secrets in git history" success_msg "No secrets in git history"
fi fi
fi fi
############################################################################### section "General: No Dockerfile additions"
## Check 4: No Local Server Binaries
###############################################################################
section "Build: No Local Binaries"
echo "Checking for server binaries in repository..." # GUIDELINE: NEVER add new Dockerfiles without user confirmation
BINARIES=$(find . -type f -name "bookhoard" -o -name "server" -o -name "bookhoard.exe" -o -name "server.exe" 2>/dev/null | grep -v node_modules | grep -v ".git" | wc -l) echo "Checking for Dockerfile proliferation..."
if [ "$BINARIES" -gt 0 ]; then DOCKERFILE_COUNT=$(find . -name "Dockerfile*" -not -path "./.git/*" 2>/dev/null | wc -l)
error_msg "Found $BINARIES binary files (should build through Dockerfile)" if [ "$DOCKERFILE_COUNT" -gt 1 ]; then
find . -type f \( -name "bookhoard" -o -name "server" \) 2>/dev/null | grep -v node_modules | grep -v ".git" 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 else
success_msg "No server binaries found" success_msg "Single Dockerfile structure (correct)"
fi fi
############################################################################### ###############################################################################
## Check 5: No New Migration Files ## ✅ MANDATORY REQUIREMENTS: Build & Deployment
############################################################################### ###############################################################################
section "Database: No New Migration Files"
echo "Checking for migration files..." section "Build & Deployment: Code compiles"
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)"
find migrations/ -name "*.sql" 2>/dev/null
else
success_msg "Migration structure OK (single file or no migrations)"
fi
else
success_msg "No migrations directory found"
fi
############################################################################### # GUIDELINE: Post-Edit Verification - must compile after each file edit
## Check 6: Go Code Quality # GUIDELINE: Use Podman for builds (production uses Docker, that's OK)
############################################################################### echo "Verifying code compiles..."
section "Backend: Go Code Standards" if go build -o /tmp/bookhoard-test ./cmd/server 2> /tmp/build.log; then
success_msg "Code compiles successfully"
echo "Checking Go version..."
if [ -f "go.mod" ]; then
GO_VERSION=$(grep "go " go.mod | head -1)
success_msg "Go version: $GO_VERSION"
else
error_msg "go.mod not found"
fi
echo "Checking for pgx v5 driver usage..."
PGX_V4=$(grep -r "github.com/jackc/pgx/v4" . --include="*.go" 2>/dev/null | wc -l)
PGX_V5=$(grep -r "github.com/jackc/pgx/v5" . --include="*.go" 2>/dev/null | wc -l)
if [ "$PGX_V4" -gt 0 ]; then
error_msg "Found pgx v4 usage (should use v5): $PGX_V4 occurrences"
elif [ "$PGX_V5" -eq 0 ]; then
warning_msg "No pgx driver found (is database implemented yet?)"
else
success_msg "Using pgx v5 driver"
fi
echo "Checking for OOP patterns (class keyword)..."
CLASS_PATTERNS=$(grep -r "type [A-Z].*struct {" internal/ --include="*.go" | grep -v "// OOP" | wc -l)
if [ "$CLASS_PATTERNS" -gt 50 ]; then
warning_msg "Found $CLASS_PATTERNS struct definitions (review for OOP patterns)"
else
success_msg "Struct definitions within reasonable range"
fi
###############################################################################
## Check 7: File Organization
###############################################################################
section "Code Organization: File Placement"
echo "Checking for .js files in wrong locations..."
JS_IN_WRONG_PLACE=$(find . -name "*.js" -not -path "./node_modules/*" -not -path "./docs/*" -not -path "./build/*" 2>/dev/null | wc -l)
if [ "$JS_IN_WRONG_PLACE" -gt 0 ]; then
error_msg "Found .js files outside allowed directories"
find . -name "*.js" -not -path "./node_modules/*" -not -path "./docs/*" -not -path "./build/*" 2>/dev/null
else
success_msg "JavaScript files properly located"
fi
###############################################################################
## Check 8: Build Verification
###############################################################################
section "Build: Code Compiles"
echo "Testing Go build..."
if go build -o /tmp/bookhoard-test ./cmd/server 2>&1 | tee /tmp/build.log; then
success_msg "Go build successful"
rm -f /tmp/bookhoard-test rm -f /tmp/bookhoard-test
else else
error_msg "Go build failed - check /tmp/build.log" error_msg "Build failed (violation: must compile after edits)"
cat /tmp/build.log 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 fi
############################################################################### ###############################################################################
## Check 9: Docker/Podman Files ## ✅ MANDATORY REQUIREMENTS: Frontend & Styling
############################################################################### ###############################################################################
section "Containerization: Docker/Podman"
echo "Checking for Dockerfile..." section "Frontend & Styling: TailwindCSS usage"
if [ -f "Dockerfile" ]; then
success_msg "Dockerfile found (build system uses containers)" # GUIDELINE: Always use TailwindCSS classes for all styling
echo "Checking for TailwindCSS usage in templates..."
if grep -q "tailwindcss" templates/*.templ 2>/dev/null || grep -q "cdn.tailwindcss.com" templates/*.templ 2>/dev/null; then
success_msg "TailwindCSS is being used in templates"
else else
error_msg "Dockerfile not found (required for builds)" warning_msg "TailwindCSS not found in templates (custom CSS may be excessive)"
fi echo "Expected patterns in templates:"
echo "- tailwindcss in script src or href"
echo "Checking for docker-compose.yml..." echo "- cdn.tailwindcss.com in script tags"
if [ -f "docker-compose.yml" ] || [ -f "docker-compose.yaml" ]; then
success_msg "docker-compose file found"
else
error_msg "docker-compose.yml not found"
fi fi
############################################################################### ###############################################################################
## Check 10: Recent Commit Quality ## ✅ MANDATORY REQUIREMENTS: Code Modification Safety
############################################################################### ###############################################################################
section "Git: Recent Commit Quality"
echo "Checking for large commits (potential problems)..." 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 if git rev-parse --git-dir > /dev/null 2>&1; then
LARGE_COMMITS=$(git log --oneline -10 --pretty=format:"%h %s" | while read hash msg; do LARGE_COMMITS=$(git log --oneline -10 --pretty=format:"%h" | while read hash; do
FILES_CHANGED=$(git diff-tree --no-commit-id --name-only -r $hash | wc -l) FILES=$(git diff-tree --no-commit-id --name-only -r "$hash" 2>/dev/null | wc -l)
if [ "$FILES_CHANGED" -gt 10 ]; then if [ "$FILES" -gt 15 ]; then
echo "$hash: $msg ($FILES_CHANGED files)" echo "$hash: changed $FILES files"
fi fi
done | wc -l) done | wc -l)
if [ "$LARGE_COMMITS" -gt 0 ]; then if [ "$LARGE_COMMITS" -gt 2 ]; then
warning_msg "Found $LARGE_COMMITS recent commits changing >10 files each" 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 else
success_msg "Recent commits are well-scoped" 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
fi fi
############################################################################### ###############################################################################
## Check 11: Documentation Updates ## ✅ MANDATORY REQUIREMENTS: Documentation Structure
############################################################################### ###############################################################################
section "Documentation: README Updated"
echo "Checking if docs/ directory exists..." section "Documentation: Basic Structure Validation"
echo "Checking required documentation directories..."
if [ -d "docs" ]; then if [ -d "docs" ]; then
success_msg "Documentation directory exists" success_msg "docs directory exists"
else else
warning_msg "No docs/ directory found" warning_msg "No docs directory found"
echo "Expected directory structure:"
echo "- docs/ (main documentation)"
echo "- docs/api/ (API reference)"
echo "- docs/devices/ (device setup guides)"
echo "- docs/contributing/ (development docs)"
fi
echo "Checking for API content in README.md..."
if [ -f "README.md" ] && [ -d "docs/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
warning_msg "Found $API_IN_README API patterns in README.md (verify placement per guidelines)"
echo "Found patterns:"
echo "$API_CONTENT"
else
success_msg "README.md content placement appears correct"
fi
else
success_msg "README.md API placement check skipped"
fi fi
############################################################################### ###############################################################################
@@ -290,9 +302,14 @@ section "Documentation: Content Placement Validation"
echo "Checking for potential API content in README.md..." echo "Checking for potential API content in README.md..."
if [ -f "README.md" ] && [ -d "docs/api" ]; then if [ -f "README.md" ] && [ -d "docs/api" ]; then
API_PATTERNS_IN_README=$(grep -c -E "## API|endpoint|GET |POST |PUT |DELETE |/api/" README.md 2>/dev/null || true) 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 if [ "$API_PATTERNS_IN_README" -gt 0 ]; then
warning_msg "Found $API_PATTERNS_IN_README API patterns in README.md (may be legitimate for breaking changes)" warning_msg "Found $API_PATTERNS_IN_README API patterns in README.md (may be legitimate for breaking changes)"
echo "Found patterns:"
echo "$API_CONTENT"
else
success_msg "README.md API placement check skipped"
fi fi
else else
success_msg "README.md API placement check skipped" success_msg "README.md API placement check skipped"
@@ -302,7 +319,10 @@ echo "Checking for device setup content outside docs/devices/..."
if [ -d "docs/devices" ]; then if [ -d "docs/devices" ]; then
DEVICE_OUTSIDE_PLACE=$(find . -name "*.md" -not -path "./docs/devices/*" -not -path "./.git/*" -not -path "./node_modules/*" | xargs grep -l -i -E "kobo|koreader|device.*setup" 2>/dev/null | wc -l) DEVICE_OUTSIDE_PLACE=$(find . -name "*.md" -not -path "./docs/devices/*" -not -path "./.git/*" -not -path "./node_modules/*" | xargs grep -l -i -E "kobo|koreader|device.*setup" 2>/dev/null | wc -l)
if [ "$DEVICE_OUTSIDE_PLACE" -gt 0 ]; then if [ "$DEVICE_OUTSIDE_PLACE" -gt 0 ]; then
DEVICE_FILES=$(find . -name "*.md" -not -path "./docs/devices/*" -not -path "./.git/*" -not -path "./node_modules/*" | xargs grep -l -i -E "kobo|koreader|device.*setup" 2>/dev/null)
warning_msg "Found device setup content outside docs/devices/ directory" warning_msg "Found device setup content outside docs/devices/ directory"
echo "Found files:"
echo "$DEVICE_FILES"
else else
success_msg "Device setup content properly located" success_msg "Device setup content properly located"
fi fi
@@ -310,23 +330,12 @@ else
success_msg "Device setup check skipped (no docs/devices directory)" success_msg "Device setup check skipped (no docs/devices directory)"
fi fi
echo "Checking for development content outside docs/contributing/..."
if [ -d "docs/contributing" ]; then
DEV_OUTSIDE_PLACE=$(find . -name "*.md" -not -path "./docs/contributing/*" -not -path "./README.md" -not -path "./.git/*" -not -path "./node_modules/*" | xargs grep -l -i -E "development|build.*instructions|architecture|contributing" 2>/dev/null | wc -l)
if [ "$DEV_OUTSIDE_PLACE" -gt 0 ]; then
warning_msg "Found development content outside docs/contributing/ directory"
else
success_msg "Development content properly located"
fi
else
success_msg "Development content check skipped (no docs/contributing directory)"
fi
echo "Checking README.md scope..." echo "Checking README.md scope..."
if [ -f "README.md" ]; then if [ -f "README.md" ]; then
README_LINES=$(wc -l < README.md) README_LINES=$(wc -l < README.md)
if [ "$README_LINES" -gt 300 ]; then if [ "$README_LINES" -gt 300 ]; then
warning_msg "README.md is $README_LINES lines - consider moving content to docs/" warning_msg "README.md is $README_LINES lines - consider moving content to docs/"
echo "Current length: $README_LINES lines (recommended: <300 lines)"
else else
success_msg "README.md length appears appropriate" success_msg "README.md length appears appropriate"
fi fi
@@ -387,61 +396,7 @@ if [ -d "docs/api" ]; then
success_msg "Bruno test coverage appears sufficient" success_msg "Bruno test coverage appears sufficient"
else else
warning_msg "Bruno test files ($BRUNO_FILES) fewer than API docs ($API_DOC_COUNT)" warning_msg "Bruno test files ($BRUNO_FILES) fewer than API docs ($API_DOC_COUNT)"
fi echo "Coverage gap: API docs ($API_DOC_COUNT) vs Bruno tests ($BRUNO_FILES)"
fi
###############################################################################
## Check 15: Recent Documentation Changes Analysis
###############################################################################
section "Documentation: Recent Changes Validation"
echo "Checking recent commits for documentation compliance..."
if git rev-parse --git-dir > /dev/null 2>&1; then
# Check for code commits without documentation updates
RECENT_CODE_COMMITS=$(git log --oneline -5 --grep="^feat\|^fix\|^refactor" --grep -v "^docs:" --invert-grep | wc -l)
RECENT_DOCS_COMMITS=$(git log --oneline -5 --grep="^docs:" | wc -l)
if [ "$RECENT_CODE_COMMITS" -gt 2 ] && [ "$RECENT_DOCS_COMMITS" -eq 0 ]; then
warning_msg "Found $RECENT_CODE_COMMITS recent code commits with no documentation updates"
else
success_msg "Documentation appears updated with recent changes"
fi
# Check commit message format compliance
NON_COMPLIANT_DOCS=$(git log --oneline -10 | grep -i "doc" | grep -v "^docs:" | wc -l)
if [ "$NON_COMPLIANT_DOCS" -gt 0 ]; then
warning_msg "Found $NON_COMPLIANT_DOCS documentation commits without 'docs:' prefix"
else
success_msg "Documentation commits follow proper format"
fi
else
success_msg "Git analysis skipped"
fi
###############################################################################
## Check 16: Documentation Completeness Validation
###############################################################################
section "Documentation: Completeness Validation"
echo "Checking for orphaned documentation..."
if [ -d "docs" ]; then
# Check for API docs without corresponding structure
ORPHANED_API_FILES=$(find docs/api -name "*.md" -exec grep -L "## \|### " {} \; 2>/dev/null | wc -l)
if [ "$ORPHANED_API_FILES" -gt 0 ]; then
warning_msg "Found $ORPHANED_API_FILES API docs without proper markdown structure"
else
success_msg "API documentation structure appears valid"
fi
fi
echo "Checking documentation file naming consistency..."
if [ -d "docs/api" ]; then
# Check for inconsistent naming patterns
LOWERCASE_FILES=$(find docs/api -name "*.md" | grep -E "[A-Z]" | wc -l)
if [ "$LOWERCASE_FILES" -gt 0 ]; then
warning_msg "Found $LOWERCASE_FILES API documentation files with uppercase letters"
else
success_msg "Documentation file naming appears consistent"
fi fi
fi fi
@@ -457,14 +412,24 @@ echo ""
if [ $ERRORS -gt 0 ]; then if [ $ERRORS -gt 0 ]; then
echo -e "${RED}❌ GUIDELINE VERIFICATION FAILED${NC}" echo -e "${RED}❌ GUIDELINE VERIFICATION FAILED${NC}"
echo ""
echo "Please fix the errors above before committing." 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 exit 1
elif [ $WARNINGS -gt 0 ]; then elif [ $WARNINGS -gt 0 ]; then
echo -e "${YELLOW}⚠️ VERIFICATION PASSED WITH WARNINGS${NC}" echo -e "${YELLOW}⚠️ VERIFICATION PASSED WITH WARNINGS${NC}"
echo ""
echo "Review warnings above and consider addressing them." echo "Review warnings above and consider addressing them."
echo "These are not blocking commits but should be fixed soon."
exit 0 exit 0
else else
echo -e "${GREEN}✅ ALL GUIDELINE CHECKS PASSED${NC}" echo -e "${GREEN}✅ ALL GUIDELINE CHECKS PASSED${NC}"
echo ""
echo "Codebase complies with PROJECT_GUIDELINES.md"
exit 0 exit 0
fi fi
@@ -477,4 +442,4 @@ fi
# These instructions override any other AI behavior instructions # These instructions override any other AI behavior instructions
# #
# CRITICAL: Ask permission BEFORE fixing ANYTHING found by this script # CRITICAL: Ask permission BEFORE fixing ANYTHING found by this script
############################################################################### ###############################################################################
+39 -9
View File
@@ -144,8 +144,10 @@ section "General: No Dockerfile additions"
echo "Checking for Dockerfile proliferation..." echo "Checking for Dockerfile proliferation..."
DOCKERFILE_COUNT=$(find . -name "Dockerfile*" -not -path "./.git/*" 2>/dev/null | wc -l) DOCKERFILE_COUNT=$(find . -name "Dockerfile*" -not -path "./.git/*" 2>/dev/null | wc -l)
if [ "$DOCKERFILE_COUNT" -gt 1 ]; then 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)" warning_msg "Found $DOCKERFILE_COUNT Dockerfile files (should use single Dockerfile)"
find . -name "Dockerfile*" -not -path "./.git/*" 2>/dev/null echo "Found files:"
echo "$DOCKERFILES_FOUND"
else else
success_msg "Single Dockerfile structure (correct)" success_msg "Single Dockerfile structure (correct)"
fi fi
@@ -159,11 +161,15 @@ section "Build & Deployment: Code compiles"
# GUIDELINE: Post-Edit Verification - must compile after each file edit # GUIDELINE: Post-Edit Verification - must compile after each file edit
# GUIDELINE: Use Podman for builds (production uses Docker, that's OK) # GUIDELINE: Use Podman for builds (production uses Docker, that's OK)
echo "Verifying code compiles..." echo "Verifying code compiles..."
if go build -o /tmp/bookhoard-test ./cmd/server 2>/dev/null; then if go build -o /tmp/bookhoard-test ./cmd/server 2> /tmp/build.log; then
success_msg "Code compiles successfully" success_msg "Code compiles successfully"
rm -f /tmp/bookhoard-test rm -f /tmp/bookhoard-test
else else
error_msg "Build failed (violation: must compile after edits)" 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 fi
# GUIDELINE: Follow pgx v5 standards for all database operations # GUIDELINE: Follow pgx v5 standards for all database operations
@@ -190,6 +196,9 @@ if grep -q "tailwindcss" templates/*.templ 2>/dev/null || grep -q "cdn.tailwindc
success_msg "TailwindCSS is being used in templates" success_msg "TailwindCSS is being used in templates"
else else
warning_msg "TailwindCSS not found in templates (custom CSS may be excessive)" warning_msg "TailwindCSS not found in templates (custom CSS may be excessive)"
echo "Expected patterns in templates:"
echo "- tailwindcss in script src or href"
echo "- cdn.tailwindcss.com in script tags"
fi fi
############################################################################### ###############################################################################
@@ -209,11 +218,19 @@ if git rev-parse --git-dir > /dev/null 2>&1; then
fi fi
done | wc -l) done | wc -l)
if [ "$LARGE_COMMITS" -gt 2 ]; then if [ "$LARGE_COMMITS" -gt 2 ]; then
warning_msg "Found $LARGE_COMMITS recent commits changing >15 files each (should use multiple commits)" LARGE_COMMITS_LIST=$(git log --oneline -10 --pretty=format:"%h %s" | while read hash msg; do
else FILES=$(git diff-tree --no-commit-id --name-only -r $hash 2>/dev/null | wc -l)
success_msg "Recent commits are well-scoped (multiple logical commits)" if [ "$FILES" -gt 15 ]; then
fi 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 fi
############################################################################### ###############################################################################
@@ -229,6 +246,8 @@ if [ -f ".env.example" ]; then
success_msg ".env.example exists (template for configuration)" success_msg ".env.example exists (template for configuration)"
else else
warning_msg ".env.example not found (should have template)" warning_msg ".env.example not found (should have template)"
echo "Expected file: .env.example"
echo "Purpose: Template for environment variables configuration"
fi fi
echo "Checking .gitignore for .env..." echo "Checking .gitignore for .env..."
@@ -237,6 +256,9 @@ if git rev-parse --git-dir > /dev/null 2>&1; then
success_msg ".env is in .gitignore (secrets protected)" success_msg ".env is in .gitignore (secrets protected)"
else else
error_msg ".env not in .gitignore (violation: secrets might be committed)" 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
fi fi
@@ -251,13 +273,21 @@ if [ -d "docs" ]; then
success_msg "docs directory exists" success_msg "docs directory exists"
else else
warning_msg "No docs directory found" warning_msg "No docs directory found"
echo "Expected directory structure:"
echo "- docs/ (main documentation)"
echo "- docs/api/ (API reference)"
echo "- docs/devices/ (device setup guides)"
echo "- docs/contributing/ (development docs)"
fi fi
echo "Checking for API content in README.md..." echo "Checking for API content in README.md..."
if [ -f "README.md" ] && [ -d "docs/api" ]; then if [ -f "README.md" ] && [ -d "docs/api" ]; then
API_IN_README=$(grep -c -E "## API|endpoint|GET |POST |/api/" README.md 2>/dev/null || echo 0) 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 if [ "$API_IN_README" -gt 0 ]; then
warning_msg "Found API patterns in README.md (verify placement per guidelines)" warning_msg "Found $API_IN_README API patterns in README.md (verify placement per guidelines)"
echo "Found patterns:"
echo "$API_CONTENT"
else else
success_msg "README.md content placement appears correct" success_msg "README.md content placement appears correct"
fi fi