ci: add automated PR validation pipeline + fix regressions

NEW: Gitea Actions CI pipeline (.gitea/workflows/pr-pipeline.yaml)
- Stage 1 (validate): YAML frontmatter validation for all .prose.md files
- Stage 2 (lint): Structural checks + regression detection
  * /grafana/ nginx route (reverted 2026-07-02)
  * Stale CT IDs (122→112, no 123)
  * Verified: .19/.122/.123 = correct bridge IPs
- Stage 3 (ai-review): LiteLLM-powered diff review against ground truth
- Stage 4 (auto-merge): Gate — safe to merge when all green

NEW: scripts/prose-lint.sh — contract structure + regression checker
NEW: scripts/prose-ai-review.sh — AI review via syslog-auto model

FIXES FOUND BY LINT:
- gpu-fleet.prose.md: removed /grafana/ from nginx routing diagram
- gpu-fleet.prose.md: removed /grafana/ from config file description
- infrastructure-control.prose.md: CT 122→112 in topology diagram
- scripts/prose-lint.sh: updated to not flag .19 (verified correct IP)
This commit is contained in:
root
2026-07-04 22:13:51 +00:00
parent dd985f0e49
commit 263c4080f3
5 changed files with 364 additions and 3 deletions
+162
View File
@@ -0,0 +1,162 @@
#!/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
REPO="${{ gitea.repository }}"
PR_NUMBER="${{ gitea.event.number }}"
BASE_REF="${{ gitea.base_ref }}"
HEAD_REF="${{ gitea.head_ref }}"
# Get the diff
echo "=== Fetching PR diff ==="
DIFF=$(git diff origin/$BASE_REF...origin/$HEAD_REF -- "*.prose.md" 2>/dev/null | head -5000)
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): abiba, kagentz, tanko, tdunna, baggy, scottdenya
- minipve (192.168.68.12): authentik, gitea, mumuni, syslog-api, jitsi
- storepve (192.168.68.6): docker-vm, ra-h-os, PBS, media, zulip
- acerpve (192.168.68.9): llm-gpu, adguard
- ocupve (192.168.68.5): ocu-llm
**CT IDs (verified 2026-07-04 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 114:mumuni 115:scottdenya 116:syslog-api 117:zulip
**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 114.
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 ==="
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