Files

247 lines
15 KiB
Bash
Raw Permalink Normal View History

2026-03-10 12:14:17 -05:00
#!/bin/bash
# Validation Script for openclaw-true-recall-base v1.3
# Tests all fixes and changes from v1.2 → v1.3
set -e
echo "╔══════════════════════════════════════════════════════════════════════════╗"
echo "║ TrueRecall Base v1.3 Validation Script ║"
echo "╚══════════════════════════════════════════════════════════════════════════╝"
echo ""
PASS=0
FAIL=0
WARN=0
check_pass() { echo "$1"; ((PASS++)); }
check_fail() { echo "$1"; ((FAIL++)); }
check_warn() { echo "⚠️ $1"; ((WARN++)); }
# ════════════════════════════════════════════════════════════════════════════
# SECTION 1: File Structure
# ════════════════════════════════════════════════════════════════════════════
echo ""
echo "═════════════════════════════════════════════════════════════════════════"
echo "SECTION 1: File Structure"
echo "═════════════════════════════════════════════════════════════════════════"
PROJECT_DIR="$(dirname "$0")"
if [ -f "$PROJECT_DIR/CHANGELOG.md" ]; then
check_pass "CHANGELOG.md exists"
else
check_fail "CHANGELOG.md missing"
fi
if [ -f "$PROJECT_DIR/watcher/realtime_qdrant_watcher.py" ]; then
check_pass "realtime_qdrant_watcher.py exists"
else
check_fail "realtime_qdrant_watcher.py missing"
fi
# Check version in file
VERSION=$(grep -m1 "TrueRecall v" "$PROJECT_DIR/watcher/realtime_qdrant_watcher.py" | grep -oE "v[0-9]+\.[0-9]+")
if [ "$VERSION" = "v1.3" ]; then
check_pass "Version is v1.3"
else
check_fail "Version mismatch: expected v1.3, got $VERSION"
fi
# ════════════════════════════════════════════════════════════════════════════
# SECTION 2: Code Changes (v1.3 Fixes)
# ════════════════════════════════════════════════════════════════════════════
echo ""
echo "═════════════════════════════════════════════════════════════════════════"
echo "SECTION 2: Code Changes (v1.3 Fixes)"
echo "═════════════════════════════════════════════════════════════════════════"
# Fix 1: FileNotFoundError check
if grep -q "if not session_file.exists():" "$PROJECT_DIR/watcher/realtime_qdrant_watcher.py"; then
check_pass "FileNotFoundError fix: Pre-check exists before open()"
else
check_fail "FileNotFoundError fix MISSING: No session_file.exists() check"
fi
if grep -q "except FileNotFoundError:" "$PROJECT_DIR/watcher/realtime_qdrant_watcher.py"; then
check_pass "FileNotFoundError fix: Exception handler present"
else
check_fail "FileNotFoundError fix MISSING: No FileNotFoundError exception handler"
fi
# Fix 2: Chunking for long content
if grep -q "def chunk_text" "$PROJECT_DIR/watcher/realtime_qdrant_watcher.py"; then
check_pass "Chunking fix: chunk_text() function defined"
else
check_fail "Chunking fix MISSING: No chunk_text() function"
fi
if grep -q "chunk_text_content" "$PROJECT_DIR/watcher/realtime_qdrant_watcher.py"; then
check_pass "Chunking fix: chunk_text_content used in store_to_qdrant()"
else
check_fail "Chunking fix MISSING: Not using chunked content"
fi
if grep -q "chunk_index" "$PROJECT_DIR/watcher/realtime_qdrant_watcher.py"; then
check_pass "Chunking fix: chunk_index metadata added"
else
check_fail "Chunking fix MISSING: No chunk_index metadata"
fi
# ════════════════════════════════════════════════════════════════════════════
# SECTION 3: Service Status
# ════════════════════════════════════════════════════════════════════════════
echo ""
echo "═════════════════════════════════════════════════════════════════════════"
echo "SECTION 3: Service Status"
echo "═════════════════════════════════════════════════════════════════════════"
if systemctl is-active --quiet mem-qdrant-watcher 2>/dev/null; then
check_pass "mem-qdrant-watcher service is running"
else
check_warn "mem-qdrant-watcher service not running (may be running in daemon mode)"
fi
# Check for running watcher process
if pgrep -f "realtime_qdrant_watcher" > /dev/null; then
check_pass "realtime_qdrant_watcher process is running"
else
check_fail "realtime_qdrant_watcher process NOT running"
fi
# ════════════════════════════════════════════════════════════════════════════
# SECTION 4: Connectivity
# ════════════════════════════════════════════════════════════════════════════
echo ""
echo "═════════════════════════════════════════════════════════════════════════"
echo "SECTION 4: Connectivity"
echo "═════════════════════════════════════════════════════════════════════════"
# Qdrant
QDRANT_URL="${QDRANT_URL:-http://10.0.0.40:6333}"
if curl -s -o /dev/null -w "%{http_code}" "$QDRANT_URL/collections/memories_tr" | grep -q "200"; then
check_pass "Qdrant memories_tr collection reachable"
else
check_fail "Qdrant memories_tr collection NOT reachable"
fi
# Ollama (local)
if curl -s -o /dev/null -w "%{http_code}" "http://localhost:11434/api/tags" | grep -q "200"; then
check_pass "Ollama (localhost) reachable"
else
check_fail "Ollama (localhost) NOT reachable"
fi
# Check embedding model
if curl -s "http://localhost:11434/api/tags" | grep -q "snowflake-arctic-embed2"; then
check_pass "Embedding model snowflake-arctic-embed2 available"
else
check_fail "Embedding model snowflake-arctic-embed2 NOT available"
fi
# ════════════════════════════════════════════════════════════════════════════
# SECTION 5: Crash Loop Test
# ════════════════════════════════════════════════════════════════════════════
echo ""
echo "═════════════════════════════════════════════════════════════════════════"
echo "SECTION 5: Crash Loop Test (Last 1 Hour)"
echo "═════════════════════════════════════════════════════════════════════════"
RESTARTS=$(journalctl -u mem-qdrant-watcher --since "1 hour ago" --no-pager 2>/dev/null | grep -c "Started mem-qdrant-watcher" || echo "0")
if [ "$RESTARTS" -le 2 ]; then
check_pass "Restarts in last hour: $RESTARTS (expected ≤2)"
else
check_fail "Restarts in last hour: $RESTARTS (too many, expected ≤2)"
fi
# Check for FileNotFoundError in logs
ERRORS=$(journalctl -u mem-qdrant-watcher --since "1 hour ago" --no-pager 2>/dev/null | grep -c "FileNotFoundError" || echo "0")
if [ "$ERRORS" -eq 0 ]; then
check_pass "No FileNotFoundError in last hour"
else
check_fail "FileNotFoundError found $ERRORS times in last hour"
fi
# ════════════════════════════════════════════════════════════════════════════
# SECTION 6: Chunking Test
# ════════════════════════════════════════════════════════════════════════════
echo ""
echo "═════════════════════════════════════════════════════════════════════════"
echo "SECTION 6: Chunking Test"
echo "═════════════════════════════════════════════════════════════════════════"
# Test chunking with Python
python3 -c "
import sys
sys.path.insert(0, '$PROJECT_DIR/watcher')
# Import chunk_text function
exec(open('$PROJECT_DIR/watcher/realtime_qdrant_watcher.py').read().split('def chunk_text')[1].split('def store_to_qdrant')[0])
# Test with long content
test_content = 'A' * 10000
chunks = chunk_text(test_content, max_chars=6000, overlap=200)
if len(chunks) > 1:
print(f'PASS: chunk_text splits 10000 chars into {len(chunks)} chunks')
sys.exit(0)
else:
print(f'FAIL: chunk_text returned {len(chunks)} chunks for 10000 chars')
sys.exit(1)
" 2>/dev/null && check_pass "chunk_text() splits long content correctly" || check_fail "chunk_text() test failed"
# ════════════════════════════════════════════════════════════════════════════
# SECTION 7: Git Status
# ════════════════════════════════════════════════════════════════════════════
echo ""
echo "═════════════════════════════════════════════════════════════════════════"
echo "SECTION 7: Git Status"
echo "═════════════════════════════════════════════════════════════════════════"
cd "$PROJECT_DIR"
# Check for v1.3 tag
if git tag -l | grep -q "v1.3"; then
check_pass "Git tag v1.3 exists"
else
check_fail "Git tag v1.3 missing"
fi
# Check CHANGELOG.md committed
if git log --oneline -1 | grep -q "v1.3"; then
check_pass "v1.3 commit in git log"
else
check_fail "v1.3 commit not found in git log"
fi
# Check for uncommitted changes
UNCOMMITTED=$(git status --short 2>/dev/null | wc -l)
if [ "$UNCOMMITTED" -eq 0 ]; then
check_pass "No uncommitted changes"
else
check_warn "$UNCOMMITTED uncommitted files"
fi
# ════════════════════════════════════════════════════════════════════════════
# SUMMARY
# ════════════════════════════════════════════════════════════════════════════
echo ""
echo "═════════════════════════════════════════════════════════════════════════"
echo "VALIDATION SUMMARY"
echo "═════════════════════════════════════════════════════════════════════════"
echo ""
echo "✅ Passed: $PASS"
echo "❌ Failed: $FAIL"
echo "⚠️ Warnings: $WARN"
echo ""
if [ $FAIL -eq 0 ]; then
echo "╔══════════════════════════════════════════════════════════════════════════╗"
echo "║ ✅ ALL VALIDATIONS PASSED - v1.3 READY FOR PRODUCTION ║"
echo "╚══════════════════════════════════════════════════════════════════════════╝"
exit 0
else
echo "╔══════════════════════════════════════════════════════════════════════════╗"
echo "║ ❌ VALIDATION FAILED - $FAIL ISSUE(S) NEED ATTENTION ║"
echo "╚══════════════════════════════════════════════════════════════════════════╝"
exit 1
fi