#!/usr/bin/env bash # Phase 44 caller-migration guard. Fails if any non-adapter file # fetches the sidecar's /generate endpoint or hits Ollama Cloud's # /api/generate directly. Adapter files (gateway provider crate + # the sidecar's own Python implementation) are exempt. # # Run: ./scripts/check_phase44_callers.sh # CI: fail-loud (exits non-zero on regression) # Watch: pre-commit hook — invoke from .git/hooks/pre-commit set -e cd "$(dirname "$0")/.." FORBIDDEN_TS=$(grep -rEln "fetch\([^)]*[/\$]generate" \ --include="*.ts" \ --exclude-dir=node_modules \ --exclude-dir=target \ --exclude-dir=.git \ . 2>/dev/null | grep -v "^\./sidecar/" || true) FORBIDDEN_RS=$(grep -rEln "post\([^)]*\"\.?/generate\"" \ --include="*.rs" \ --exclude-dir=target \ . 2>/dev/null | \ grep -vE "^\./crates/(gateway|aibridge)/" || true) # Ollama Cloud /api/generate outside the gateway adapter. Match only # when the URL appears in an actual fetch/post call (not in a comment). # Tightened 2026-04-27 — pre-tightening regex flagged prose mentions. FORBIDDEN_CLOUD=$(grep -rEln "(fetch|client\.post)\([^)]*api/generate" \ --include="*.ts" --include="*.rs" \ --exclude-dir=node_modules \ --exclude-dir=target \ --exclude-dir=.git \ . 2>/dev/null | \ grep -vE "^\./(crates/gateway|sidecar)" || true) ANY_FAIL=0 if [ -n "$FORBIDDEN_TS" ]; then echo "❌ Direct sidecar /generate calls (migrate to /v1/chat):" echo "$FORBIDDEN_TS" | sed 's/^/ /' ANY_FAIL=1 fi if [ -n "$FORBIDDEN_RS" ]; then echo "❌ Direct Rust /generate post() calls (migrate via gateway adapter):" echo "$FORBIDDEN_RS" | sed 's/^/ /' ANY_FAIL=1 fi if [ -n "$FORBIDDEN_CLOUD" ]; then echo "❌ Direct Ollama Cloud /api/generate (migrate to gateway provider=ollama_cloud):" echo "$FORBIDDEN_CLOUD" | sed 's/^/ /' ANY_FAIL=1 fi if [ $ANY_FAIL -eq 0 ]; then echo "✅ Phase 44 caller-migration: clean (no direct /generate outside adapters)" fi exit $ANY_FAIL