#!/bin/bash # prose-ai-review.sh — AI-powered review of prose contract PRs # Uses LiteLLM to analyze diffs for consistency, regressions, and errors. # Posts review comments via Gitea API. set -euo pipefail LITELLM_URL="${LITELLM_URL:-https://litellm.sysloggh.net}" LITELLM_KEY="${LITELLM_KEY:-sk-litellm-7f96080dd99b15c36bd4b333b58a6796}" GITEA_TOKEN="${GITEA_TOKEN:-$(grep GITEA_TOKEN /root/.pi/agent/extensions/telegram/.env 2>/dev/null | cut -d= -f2 || echo '')}" GITEA_API="https://git.sysloggh.net/api/v1" # Get PR context from Gitea Actions environment # For push events: GITEA_REPOSITORY, GITEA_SHA REPO="${GITEA_REPOSITORY:-}" BASE_REF="${GITEA_BASE_REF:-refs/heads/master}" HEAD_REF="${GITEA_HEAD_REF:-}" SHA="${GITEA_SHA:-}" # Get the diff — works for both PR events (base...head) and push events (HEAD~1) echo "=== Fetching diff ===" if [ -n "$HEAD_REF" ] && [ "$HEAD_REF" != "$BASE_REF" ]; then DIFF=$(git diff origin/$BASE_REF...origin/$HEAD_REF -- "*.prose.md" 2>/dev/null | head -5000) elif [ -n "$SHA" ]; then DIFF=$(git diff $SHA~1..$SHA -- "*.prose.md" 2>/dev/null | head -5000) else DIFF=$(git diff HEAD~1 -- "*.prose.md" 2>/dev/null | head -5000) fi if [ -z "$DIFF" ]; then echo "No prose contract changes in this PR. Skipping AI review." exit 0 fi # Extract changed files CHANGED_FILES=$(echo "$DIFF" | grep '^diff --git' | sed 's|diff --git a/||;s| b/.*||' | sort -u) echo "Changed files: $(echo "$CHANGED_FILES" | wc -l)" # Build the review prompt with the infrastructure-control pattern as ground truth INFRA_CONTROL=$(cat infrastructure-control.prose.md 2>/dev/null | head -200 || echo "unavailable") REVIEW_PROMPT=$(cat </dev/null) if [ -z "$RESPONSE" ]; then echo "❌ LiteLLM review API call failed" exit 1 fi REVIEW_BODY=$(echo "$RESPONSE" | python3 -c " import json, sys d = json.load(sys.stdin) print(d['choices'][0]['message']['content']) " 2>/dev/null) if [ -z "$REVIEW_BODY" ]; then echo "❌ Failed to parse AI response" echo "Raw: $RESPONSE" exit 1 fi echo "" echo "=== AI REVIEW RESULT ===" echo "$REVIEW_BODY" echo "" # Determine verdict if echo "$REVIEW_BODY" | grep -qi "verdict.*CHANGES_REQUESTED"; then VERDICT="CHANGES_REQUESTED" EVENT="REQUEST_CHANGES" else VERDICT="APPROVED" EVENT="APPROVE" fi # Post review to Gitea PR echo "=== Posting review to PR #$PR_NUMBER ===" if [ -n "$GITEA_TOKEN" ]; then curl -sf -X POST "$GITEA_API/repos/$REPO/pulls/$PR_NUMBER/reviews" \ -H "Authorization: token $GITEA_TOKEN" \ -H "Content-Type: application/json" \ -d "$(python3 -c " import json print(json.dumps({ 'body': '$REVIEW_BODY', 'event': '$EVENT' })) ")" 2>/dev/null || echo "⚠️ Could not post review via API (token may be missing)" echo "✅ AI review posted: $VERDICT" else echo "⚠️ GITEA_TOKEN not set — review displayed above but not posted to PR" fi # Exit with error if changes requested (blocks merge) if [ "$VERDICT" = "CHANGES_REQUESTED" ]; then exit 1 fi