ggen-cli-lib 26.7.3

CLI interface for ggen
Documentation
#!/usr/bin/env bash
# =============================================================================
# ln_ctrl Verification Script - Verify Generated Code
#
# Runs verifier only (no sync). Validates generated artifacts against ontology.
#
# Generated by ggen from ln_ctrl wizard - DO NOT EDIT MANUALLY
# Regenerate with: ggen sync --audit true
# =============================================================================

set -euo pipefail

# Configuration
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
readonly GENERATED_DIR="${PROJECT_ROOT}/generated"
readonly ONTOLOGY_DIR="${PROJECT_ROOT}/ontologies"
readonly LOG_DIR="${PROJECT_ROOT}/logs"

# Colors
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly CYAN='\033[0;36m'
readonly NC='\033[0m'

# Flags
VERBOSE=false
QUICK=false

# Ensure directories exist
mkdir -p "${LOG_DIR}"

# Print functions
print_pass() { echo -e "${GREEN}✅ PASS${NC}: $*"; }
print_fail() { echo -e "${RED}❌ FAIL${NC}: $*"; }
print_info() { echo -e "${BLUE}ℹ️  INFO${NC}: $*"; }
print_warn() { echo -e "${YELLOW}⚠️  WARN${NC}: $*"; }
print_step() { echo -e "${CYAN}${NC}  $*"; }

# Usage
usage() {
    cat << 'EOF'
ln_ctrl Verification Script - Verify Generated Code

Runs verification checks on generated artifacts without triggering sync.

Usage: ./verify.sh [options]

Options:
    -q, --quick        Quick verification (skip expensive checks)
    -v, --verbose      Enable verbose output
    -h, --help         Show this help message

Verification Steps:
    1. Check generated directory exists
    2. Verify file structure
    3. Run cargo check (if Rust code generated)
    4. Run cargo test (if tests exist)
    5. Verify hash consistency (determinism check)

Examples:
    ./verify.sh                # Full verification
    ./verify.sh --quick        # Quick checks only
    ./verify.sh --verbose      # Detailed output

Exit codes:
    0 - Verification passed
    1 - Verification failed
    2 - Error (missing files, invalid setup)

EOF
}

# Check generated directory
check_generated_dir() {
    print_step "Checking generated directory..."

    if [[ ! -d "${GENERATED_DIR}" ]]; then
        print_fail "Generated directory not found: ${GENERATED_DIR}"
        print_info "Run ./run.sh first to generate code"
        return 1
    fi

    local file_count
    file_count=$(find "${GENERATED_DIR}" -type f 2>/dev/null | wc -l)

    if [[ $file_count -eq 0 ]]; then
        print_fail "Generated directory is empty"
        return 1
    fi

    print_pass "Found ${file_count} generated files"
    return 0
}

# Verify file structure
verify_file_structure() {
    print_step "Verifying file structure..."

    local failures=0

    # Check for expected files/directories
    local expected_items=(
        "Cargo.toml"
        "src"
    )

    for item in "${expected_items[@]}"; do
        local item_path="${GENERATED_DIR}/${item}"
        if [[ -e "$item_path" ]]; then
            if [[ "$VERBOSE" == "true" ]]; then
                print_info "Found: ${item}"
            fi
        else
            if [[ "$VERBOSE" == "true" ]]; then
                print_warn "Missing: ${item}"
            fi
        fi
    done

    print_pass "File structure verified"
    return 0
}

# Run cargo check
run_cargo_check() {
    print_step "Running cargo check..."

    local cargo_toml="${GENERATED_DIR}/Cargo.toml"

    if [[ ! -f "$cargo_toml" ]]; then
        print_info "No Cargo.toml found, skipping cargo check"
        return 0
    fi

    local log_file="${LOG_DIR}/cargo-check-$(date +%Y%m%d-%H%M%S).log"

    if [[ "$VERBOSE" == "true" ]]; then
        if cargo check --manifest-path "$cargo_toml" 2>&1 | tee "$log_file"; then
            print_pass "Cargo check passed"
            return 0
        else
            print_fail "Cargo check failed (see ${log_file})"
            return 1
        fi
    else
        if cargo check --manifest-path "$cargo_toml" > "$log_file" 2>&1; then
            print_pass "Cargo check passed"
            return 0
        else
            print_fail "Cargo check failed (see ${log_file})"
            tail -n 20 "$log_file"
            return 1
        fi
    fi
}

# Run cargo test
run_cargo_test() {
    print_step "Running cargo test..."

    if [[ "$QUICK" == "true" ]]; then
        print_info "Skipping tests (quick mode)"
        return 0
    fi

    local cargo_toml="${GENERATED_DIR}/Cargo.toml"

    if [[ ! -f "$cargo_toml" ]]; then
        print_info "No Cargo.toml found, skipping cargo test"
        return 0
    fi

    local log_file="${LOG_DIR}/cargo-test-$(date +%Y%m%d-%H%M%S).log"

    if [[ "$VERBOSE" == "true" ]]; then
        if cargo test --manifest-path "$cargo_toml" 2>&1 | tee "$log_file"; then
            print_pass "All tests passed"
            return 0
        else
            print_fail "Some tests failed (see ${log_file})"
            return 1
        fi
    else
        if cargo test --manifest-path "$cargo_toml" > "$log_file" 2>&1; then
            local test_count
            test_count=$(grep -oP '\d+(?= passed)' "$log_file" | tail -1 || echo "0")
            print_pass "All ${test_count} tests passed"
            return 0
        else
            print_fail "Some tests failed (see ${log_file})"
            tail -n 20 "$log_file"
            return 1
        fi
    fi
}

# Verify hash consistency (determinism)
verify_hash_consistency() {
    print_step "Verifying hash consistency..."

    if [[ "$QUICK" == "true" ]]; then
        print_info "Skipping hash verification (quick mode)"
        return 0
    fi

    # Compute hash of all generated files
    local hash_file="${GENERATED_DIR}/.ggen-hash"
    local current_hash

    current_hash=$(find "${GENERATED_DIR}" -type f ! -path "*/target/*" ! -name ".ggen-hash" -exec sha256sum {} \; 2>/dev/null | sort | sha256sum | cut -d' ' -f1)

    if [[ -f "$hash_file" ]]; then
        local stored_hash
        stored_hash=$(cat "$hash_file")

        if [[ "$current_hash" == "$stored_hash" ]]; then
            print_pass "Hash consistency verified (deterministic generation)"
        else
            print_warn "Hash mismatch (non-deterministic generation detected)"
            if [[ "$VERBOSE" == "true" ]]; then
                print_info "Stored:  ${stored_hash}"
                print_info "Current: ${current_hash}"
            fi
        fi
    else
        # Store hash for future comparisons
        echo "$current_hash" > "$hash_file"
        print_info "Baseline hash stored"
    fi

    return 0
}

# Print summary
print_summary() {
    local failures="$1"

    echo ""
    echo "=============================================="
    echo "ln_ctrl Verification Summary"
    echo "=============================================="
    echo "Project:      ${PROJECT_ROOT}"
    echo "Generated:    ${GENERATED_DIR}"
    echo "Timestamp:    $(date -u +"%Y-%m-%dT%H:%M:%SZ")"
    echo "----------------------------------------------"

    if [[ $failures -eq 0 ]]; then
        echo -e "${GREEN}RESULT: PASS${NC}"
        echo "=============================================="
        echo ""
        return 0
    else
        echo -e "${RED}RESULT: FAIL (${failures} failures)${NC}"
        echo "=============================================="
        echo ""
        return 1
    fi
}

# Main execution
main() {
    # Parse arguments
    while [[ $# -gt 0 ]]; do
        case "$1" in
            -q|--quick)
                QUICK=true
                shift
                ;;
            -v|--verbose)
                VERBOSE=true
                shift
                ;;
            -h|--help)
                usage
                exit 0
                ;;
            *)
                echo "Unknown option: $1"
                usage
                exit 2
                ;;
        esac
    done

    echo ""
    echo "=============================================="
    echo "ln_ctrl Verification"
    echo "=============================================="
    echo "Verifying generated artifacts..."
    echo "----------------------------------------------"
    echo ""

    local failures=0

    # Run verification steps
    check_generated_dir || ((failures++))

    if [[ $failures -eq 0 ]]; then
        verify_file_structure || ((failures++))
        run_cargo_check || ((failures++))
        run_cargo_test || ((failures++))
        verify_hash_consistency || ((failures++))
    else
        print_fail "Cannot proceed with verification (generated directory check failed)"
    fi

    # Print summary and exit
    print_summary "$failures"
}

main "$@"