Files
prose-contracts/scripts/prose-ai-review.sh
T
kagentz-bot 44f7008302
PR Pipeline — Authorize → Validate → Review → Merge / auth (pull_request) Successful in 6s
PR Pipeline — Authorize → Validate → Review → Merge / validate (pull_request) Successful in 1s
PR Pipeline — Authorize → Validate → Review → Merge / lint (pull_request) Successful in 1s
PR Pipeline — Authorize → Validate → Review → Merge / ai-review (pull_request) Successful in 3s
PR Pipeline — Authorize → Validate → Review → Merge / gate (pull_request) Successful in 2s
docs: reflect hwepve removal from Tabiri cluster (5 nodes + standalone London node)
- Remove hwepve from cluster member lists/diagrams in infrastructure-control,
  proxmox-monitor, infrastructure-update, litellm-health, mumuni-delegation
- CTs 100 (abiba) and 105 (kagentz) moved to minipve; CT 114 (mumuni) no longer
  exists (Mumuni runs inside Abiba CT 100)
- Add standalone London role + NetBird routing peer description for hwepve
- Update scripts: agent-health-check.py, pct-run.sh, prose-ai-review.sh
- Update disk-gc CT access table, hermes baselines/restore host references
2026-08-15 20:03:02 -04:00

178 lines
5.8 KiB
Bash
Executable File

#!/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:-}"
LITELLM_KEY="${LITELLM_KEY:-}"
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 <<PROMPT
You are a code reviewer for OpenProse infrastructure contracts in the Syslog Solution LLC environment.
## INFRASTRUCTURE GROUND TRUTH
The infrastructure-control.prose.md contract is the canonical reference for the cluster topology:
**Proxmox Cluster "Tabiri" (5 nodes):**
- amdpve (192.168.68.15): tanko, tdunna, baggy, scottdenya
- minipve (192.168.68.12): abiba, kagentz, adguard, authentik, gitea, syslog-api, infisical-vault
- storepve (192.168.68.6): docker-vm, ra-h-os, PBS, media, jdownloader, zulip
- acerpve (192.168.68.9): llm-gpu
- ocupve (192.168.68.5): ocu-llm
**CT IDs (verified 2026-07-24 against PVE API):**
100:abiba 102:adguard 104:authentik 105:kagentz 106:ra-h-os
107:pbs 108:media 110:gitea 111:tdunna 112:tanko
113:baggy 115:scottdenya 116:syslog-api 117:zulip
118:jdownloader 119:infisical-vault
**NO CT 122, CT 123, or .19 exist in the cluster.**
**CRITICAL RULES (never regress):**
1. NO /grafana/ nginx route — it was tried and reverted on 2026-07-02. Grafana is direct LAN at :3001.
2. NO .19 IP — Zulip is CT 117 on storepve.
3. NO CT 122/123 — Tanko=CT 112, Mumuni=CT 100 (inside Abiba). No CT 114 anywhere.
4. Strix Halo :8080 is FIREWALLED to .116 only — cannot be probed from abiba (.24).
5. abiba-zulip PM2 process is DECOMMISSIONED (2026-07-04) — abiba uses Telegram only.
**Docker on CT 116 (8 containers):**
harness-litellm, harness-router, harness-nginx, harness-postgres,
harness-redis, harness-dashboard, harness-grafana, harness-prometheus
## DIFF TO REVIEW
$DIFF
## REVIEW INSTRUCTIONS
Check the diff for:
1. Does it introduce any contradictions with the ground truth above?
2. Does it re-introduce any previously-fixed issues (Grafana /grafana/ route, stale CT IDs, .19)?
3. Are any IPs or hostnames wrong?
4. Does the frontmatter have valid kind, name, and description fields?
5. Is anything inconsistent with other contracts in the repo?
Respond with a concise review in this format:
**Verdict:** APPROVED / CHANGES_REQUESTED
**Issues found:**
- [issue 1]
- [issue 2]
**Summary:** (one paragraph summary of the changes)
PROMPT
)
echo "=== Sending to LiteLLM for review ==="
# Skip if LiteLLM is not configured (secrets not available)
if [ -z "${LITELLM_URL:-}" ] || [ -z "${LITELLM_KEY:-}" ]; then
echo "⚠️ LiteLLM secrets not configured — skipping AI review"
echo " Set LITELLM_URL and LITELLM_KEY as Gitea repository secrets"
exit 0
fi
RESPONSE=$(curl -sf -X POST "$LITELLM_URL/v1/chat/completions" \
-H "Authorization: Bearer $LITELLM_KEY" \
-H "Content-Type: application/json" \
-d "$(python3 -c "
import json, sys
print(json.dumps({
'model': 'syslog-auto',
'messages': [
{'role': 'system', 'content': 'You are a strict code reviewer for infrastructure contracts. Be concise. Never approve changes that contradict the ground truth.'},
{'role': 'user', 'content': '''$REVIEW_PROMPT'''}
],
'temperature': 0.1,
'max_tokens': 1500
}))
")" 2>/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