Timothy Eastridge commited on
Commit
ead5455
·
1 Parent(s): 28e46ad

commit step 10

Browse files
ops/scripts/acceptance_test.md ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # MVP Acceptance Test Checklist
2
+
3
+ ## Pre-requisites
4
+ - [ ] Docker and Docker Compose installed
5
+ - [ ] LLM API key configured in `.env`
6
+ - [ ] All containers running (`docker-compose up -d`)
7
+
8
+ ## Test Scenarios
9
+
10
+ ### Scenario 1: Basic Query Flow
11
+ 1. [ ] Open http://localhost:3000
12
+ 2. [ ] Type: "Show all customers"
13
+ 3. [ ] Verify workflow created message appears
14
+ 4. [ ] Verify graph visualization updates
15
+ 5. [ ] Wait for results (may take 5+ minutes due to pauses)
16
+ 6. [ ] Verify table with customer data appears
17
+ 7. [ ] Verify SQL query is displayed
18
+
19
+ ### Scenario 2: Human Intervention
20
+ 1. [ ] Start new query: "Count all orders"
21
+ 2. [ ] During the 5-minute pause (watch agent logs)
22
+ 3. [ ] Open Neo4j Browser: http://localhost:7474
23
+ 4. [ ] Run query: `MATCH (i:Instruction {status: 'pending', type: 'generate_sql'}) RETURN i`
24
+ 5. [ ] Edit instruction: `SET i.parameters = '{"question": "Count orders with status completed"}'`
25
+ 6. [ ] Verify agent uses modified query after pause
26
+ 7. [ ] Verify results reflect the change
27
+
28
+ ### Scenario 3: Stop Workflow
29
+ 1. [ ] Start query: "Find expensive orders"
30
+ 2. [ ] Click STOP button during execution
31
+ 3. [ ] Verify workflow stops
32
+ 4. [ ] Check Neo4j: `MATCH (w:Workflow) RETURN w.status` shows 'stopped'
33
+
34
+ ### Scenario 4: Graph Visualization
35
+ 1. [ ] Start any query
36
+ 2. [ ] Verify workflow node appears (blue/gray)
37
+ 3. [ ] Verify instruction nodes appear
38
+ 4. [ ] Verify colors change:
39
+ - Gray = pending
40
+ - Yellow = executing
41
+ - Green = complete
42
+ 5. [ ] Click on node shows properties
43
+
44
+ ### Scenario 5: Audit Trail
45
+ 1. [ ] After running queries, open Neo4j Browser
46
+ 2. [ ] Run: `MATCH (l:Log) RETURN l ORDER BY l.timestamp DESC LIMIT 10`
47
+ 3. [ ] Verify all MCP operations are logged
48
+ 4. [ ] Run: `MATCH (e:Execution) RETURN e`
49
+ 5. [ ] Verify all executions have results
50
+
51
+ ## Performance Checks
52
+ - [ ] Agent processes instructions within 30 seconds of becoming available
53
+ - [ ] Frontend responds within 1 second
54
+ - [ ] Graph updates within 10 seconds
55
+ - [ ] No memory leaks after 10+ queries
56
+
57
+ ## Data Validation
58
+ Run these queries in Neo4j Browser:
59
+
60
+ ```cypher
61
+ // Check schema discovered
62
+ MATCH (t:Table) RETURN t.name
63
+
64
+ // Check instructions executed
65
+ MATCH (i:Instruction)-[:EXECUTED_AS]->(e:Execution)
66
+ RETURN i.type, i.status, e.completed_at
67
+
68
+ // Check successful SQL generation
69
+ MATCH (qt:QueryTemplate)
70
+ RETURN qt.query, qt.created_at
71
+ ORDER BY qt.created_at DESC
72
+ LIMIT 5
73
+
74
+ // Check workflow completion rate
75
+ MATCH (w:Workflow)
76
+ RETURN w.status, count(w) as count
77
+ ```
78
+
79
+ ## Sign-off
80
+ - [ ] All test scenarios pass
81
+ - [ ] No errors in container logs
82
+ - [ ] System recovers from agent restart
83
+ - [ ] Clean startup from `docker-compose down && docker-compose up -d`
84
+
85
+ **Tester:** _________________
86
+ **Date:** _________________
87
+ **Version:** MVP 1.0
88
+
89
+ ---
90
+
91
+ ## Final validation commands:
92
+
93
+ ```bash
94
+ # Complete test sequence
95
+ docker-compose down
96
+ docker-compose up -d
97
+ sleep 10
98
+
99
+ # Check health
100
+ curl -s http://localhost:8000/health && echo "MCP: OK"
101
+ curl -s http://localhost:3000 > /dev/null && echo "Frontend: OK"
102
+
103
+ # Seed data
104
+ docker-compose exec mcp python /app/ops/scripts/seed.py
105
+
106
+ # Run automated validation
107
+ docker-compose exec mcp python /app/ops/scripts/validate.py
108
+
109
+ # Run demo
110
+ bash ops/scripts/demo.sh
111
+
112
+ # In another terminal, watch all logs
113
+ docker-compose logs -f
114
+
115
+ # Manual test in another terminal
116
+ curl -X POST http://localhost:8000/mcp \
117
+ -H "Content-Type: application/json" \
118
+ -H "X-API-Key: dev-key-123" \
119
+ -d '{
120
+ "tool": "write_graph",
121
+ "params": {
122
+ "action": "create_node",
123
+ "label": "Instruction",
124
+ "properties": {
125
+ "id": "final-test",
126
+ "type": "generate_sql",
127
+ "status": "pending",
128
+ "sequence": 999,
129
+ "pause_duration": 30,
130
+ "parameters": "{\"question\": \"What is the total revenue from all orders?\"}"
131
+ }
132
+ }
133
+ }'
134
+
135
+ # Check execution after ~30 seconds
136
+ curl -X POST http://localhost:8000/mcp \
137
+ -H "Content-Type: application/json" \
138
+ -H "X-API-Key: dev-key-123" \
139
+ -d '{
140
+ "tool": "query_graph",
141
+ "params": {
142
+ "query": "MATCH (i:Instruction {id: \"final-test\"})-[:EXECUTED_AS]->(e:Execution) RETURN e.result"
143
+ }
144
+ }'
145
+ ```
ops/scripts/demo.ps1 ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Graph-Driven Agent Demo Script for PowerShell
2
+ # Run this with: powershell -ExecutionPolicy Bypass -File ops/scripts/demo.ps1
3
+
4
+ Write-Host "🚀 Graph-Driven Agent Demo" -ForegroundColor Green
5
+ Write-Host "=========================" -ForegroundColor Green
6
+ Write-Host ""
7
+
8
+ Write-Host "Step 1: Starting services..." -ForegroundColor Blue
9
+ docker-compose up -d
10
+ Start-Sleep 10
11
+
12
+ Write-Host "Step 2: Checking health..." -ForegroundColor Blue
13
+
14
+ Write-Host "Checking Neo4j..." -ForegroundColor Cyan
15
+ docker-compose exec neo4j cypher-shell -u neo4j -p password "MATCH (n) RETURN count(n) LIMIT 1" 2>$null
16
+ if ($LASTEXITCODE -eq 0) {
17
+ Write-Host "✅ Neo4j: Healthy" -ForegroundColor Green
18
+ } else {
19
+ Write-Host "❌ Neo4j: Unhealthy" -ForegroundColor Red
20
+ }
21
+
22
+ Write-Host "Checking PostgreSQL..." -ForegroundColor Cyan
23
+ docker-compose exec postgres pg_isready -U postgres 2>$null
24
+ if ($LASTEXITCODE -eq 0) {
25
+ Write-Host "✅ PostgreSQL: Healthy" -ForegroundColor Green
26
+ } else {
27
+ Write-Host "❌ PostgreSQL: Unhealthy" -ForegroundColor Red
28
+ }
29
+
30
+ Write-Host "Checking MCP Server..." -ForegroundColor Cyan
31
+ try {
32
+ $response = Invoke-WebRequest -Uri "http://localhost:8000/health" -UseBasicParsing -TimeoutSec 5
33
+ if ($response.StatusCode -eq 200) {
34
+ Write-Host "✅ MCP Server: Healthy" -ForegroundColor Green
35
+ } else {
36
+ Write-Host "❌ MCP Server: Unhealthy" -ForegroundColor Red
37
+ }
38
+ } catch {
39
+ Write-Host "❌ MCP Server: Unhealthy" -ForegroundColor Red
40
+ }
41
+
42
+ Write-Host "Checking Frontend..." -ForegroundColor Cyan
43
+ try {
44
+ $response = Invoke-WebRequest -Uri "http://localhost:3000" -UseBasicParsing -TimeoutSec 5
45
+ if ($response.StatusCode -eq 200) {
46
+ Write-Host "✅ Frontend: Healthy" -ForegroundColor Green
47
+ } else {
48
+ Write-Host "❌ Frontend: Unhealthy" -ForegroundColor Red
49
+ }
50
+ } catch {
51
+ Write-Host "❌ Frontend: Unhealthy" -ForegroundColor Red
52
+ }
53
+
54
+ Write-Host "Checking Agent..." -ForegroundColor Cyan
55
+ $agentStatus = docker-compose ps agent | Select-String "Up"
56
+ if ($agentStatus) {
57
+ Write-Host "✅ Agent: Running" -ForegroundColor Green
58
+ } else {
59
+ Write-Host "❌ Agent: Not running" -ForegroundColor Red
60
+ }
61
+
62
+ Write-Host ""
63
+ Write-Host "Step 3: Seeding demo workflow..." -ForegroundColor Blue
64
+ docker-compose exec mcp python /app/ops/scripts/seed.py
65
+
66
+ Write-Host ""
67
+ Write-Host "✅ Demo environment ready!" -ForegroundColor Green
68
+ Write-Host ""
69
+ Write-Host "📝 Demo Instructions:" -ForegroundColor Yellow
70
+ Write-Host "-------------------" -ForegroundColor Yellow
71
+ Write-Host "1. Open http://localhost:3000 in your browser" -ForegroundColor White
72
+ Write-Host ""
73
+ Write-Host "2. In the chat, type: 'Show me customers who have ordered more than `$100'" -ForegroundColor White
74
+ Write-Host ""
75
+ Write-Host "3. You'll see:" -ForegroundColor White
76
+ Write-Host " - 'Workflow created!' message" -ForegroundColor Gray
77
+ Write-Host " - Graph visualization showing workflow nodes" -ForegroundColor Gray
78
+ Write-Host " - Status showing 'Agent thinking...'" -ForegroundColor Gray
79
+ Write-Host ""
80
+ Write-Host "4. The agent will:" -ForegroundColor White
81
+ Write-Host " - Pause for 5 minutes (or configured duration)" -ForegroundColor Gray
82
+ Write-Host " - Discover PostgreSQL schema" -ForegroundColor Gray
83
+ Write-Host " - Generate SQL query" -ForegroundColor Gray
84
+ Write-Host " - Execute and return results" -ForegroundColor Gray
85
+ Write-Host ""
86
+ Write-Host "5. During the pause, you can:" -ForegroundColor White
87
+ Write-Host " - Open Neo4j Browser: http://localhost:7474" -ForegroundColor Gray
88
+ Write-Host " - Login: neo4j/password" -ForegroundColor Gray
89
+ Write-Host " - Run: MATCH (i:Instruction {status: 'pending'}) RETURN i" -ForegroundColor Gray
90
+ Write-Host " - Edit parameters to change the query" -ForegroundColor Gray
91
+ Write-Host ""
92
+ Write-Host "6. After execution completes:" -ForegroundColor White
93
+ Write-Host " - Results appear in a table" -ForegroundColor Gray
94
+ Write-Host " - Generated SQL is shown" -ForegroundColor Gray
95
+ Write-Host " - Graph shows all nodes as green (complete)" -ForegroundColor Gray
96
+ Write-Host ""
97
+ Write-Host "Optional: Edit instruction during pause" -ForegroundColor Yellow
98
+ Write-Host "docker-compose exec neo4j cypher-shell -u neo4j -p password \"
99
+ Write-Host " \"MATCH (i:Instruction {type: 'generate_sql', status: 'pending'}) \"
100
+ Write-Host " SET i.parameters = '{\"question\": \"Count all orders\"}'\""
101
+ Write-Host ""
102
+ Write-Host "🎉 DEMO IS RUNNING!" -ForegroundColor Green
103
+ Write-Host "Press Ctrl+C to stop monitoring logs." -ForegroundColor Yellow
104
+ Write-Host ""
105
+
106
+ # Keep running and show agent logs
107
+ Write-Host "Monitoring agent logs..." -ForegroundColor Blue
108
+ docker-compose logs -f agent
ops/scripts/demo.sh ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ echo "🚀 Graph-Driven Agent Demo"
4
+ echo "========================="
5
+ echo ""
6
+
7
+ # Colors for output
8
+ GREEN='\033[0;32m'
9
+ BLUE='\033[0;34m'
10
+ YELLOW='\033[1;33m'
11
+ NC='\033[0m' # No Color
12
+
13
+ echo -e "${BLUE}Step 1: Starting services...${NC}"
14
+ docker-compose up -d
15
+ sleep 10
16
+
17
+ echo -e "${BLUE}Step 2: Checking health...${NC}"
18
+ echo "Checking Neo4j..."
19
+ docker-compose exec neo4j cypher-shell -u neo4j -p password "MATCH (n) RETURN count(n) LIMIT 1" > /dev/null 2>&1 && echo "✅ Neo4j: Healthy" || echo "❌ Neo4j: Unhealthy"
20
+
21
+ echo "Checking PostgreSQL..."
22
+ docker-compose exec postgres pg_isready -U postgres > /dev/null 2>&1 && echo "✅ PostgreSQL: Healthy" || echo "❌ PostgreSQL: Unhealthy"
23
+
24
+ echo "Checking MCP Server..."
25
+ curl -s http://localhost:8000/health > /dev/null && echo "✅ MCP Server: Healthy" || echo "❌ MCP Server: Unhealthy"
26
+
27
+ echo "Checking Frontend..."
28
+ curl -s http://localhost:3000 > /dev/null && echo "✅ Frontend: Healthy" || echo "❌ Frontend: Unhealthy"
29
+
30
+ echo "Checking Agent..."
31
+ docker-compose ps agent | grep -q "Up" && echo "✅ Agent: Running" || echo "❌ Agent: Not running"
32
+
33
+ echo -e "${BLUE}Step 3: Seeding demo workflow...${NC}"
34
+ docker-compose exec mcp python /app/ops/scripts/seed.py
35
+
36
+ echo -e "${GREEN}✅ Demo environment ready!${NC}"
37
+ echo ""
38
+ echo "📝 Demo Script:"
39
+ echo "---------------"
40
+ echo "1. Open http://localhost:3000 in your browser"
41
+ echo ""
42
+ echo "2. In the chat, type: 'Show me customers who have ordered more than \$100'"
43
+ echo ""
44
+ echo "3. You'll see:"
45
+ echo " - 'Workflow created!' message"
46
+ echo " - Graph visualization showing workflow nodes"
47
+ echo " - Status showing 'Agent thinking...'"
48
+ echo ""
49
+ echo "4. The agent will:"
50
+ echo " - Pause for 5 minutes (or configured duration)"
51
+ echo " - Discover PostgreSQL schema"
52
+ echo " - Generate SQL query"
53
+ echo " - Execute and return results"
54
+ echo ""
55
+ echo "5. During the pause, you can:"
56
+ echo " - Open Neo4j Browser: http://localhost:7474"
57
+ echo " - Login: neo4j/password"
58
+ echo " - Run: MATCH (i:Instruction {status: 'pending'}) RETURN i"
59
+ echo " - Edit parameters to change the query"
60
+ echo ""
61
+ echo "6. After execution completes:"
62
+ echo " - Results appear in a table"
63
+ echo " - Generated SQL is shown"
64
+ echo " - Graph shows all nodes as green (complete)"
65
+ echo ""
66
+ echo -e "${YELLOW}Optional: Edit instruction during pause${NC}"
67
+ echo "docker-compose exec neo4j cypher-shell -u neo4j -p password \\"
68
+ echo " \"MATCH (i:Instruction {type: 'generate_sql', status: 'pending'}) \\"
69
+ echo " SET i.parameters = '{\\\"question\\\": \\\"Count all orders\\\"}'\""
70
+ echo ""
71
+ echo -e "${GREEN}Demo is running! Press Ctrl+C to stop.${NC}"
72
+
73
+ # Keep running
74
+ docker-compose logs -f agent
ops/scripts/validate.py ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Validate that the MVP system is working correctly"""
3
+
4
+ import requests
5
+ import time
6
+ import json
7
+ import sys
8
+
9
+ MCP_URL = "http://localhost:8000/mcp"
10
+ API_KEY = "dev-key-123"
11
+
12
+ def call_mcp(tool, params=None):
13
+ response = requests.post(
14
+ MCP_URL,
15
+ headers={"X-API-Key": API_KEY, "Content-Type": "application/json"},
16
+ json={"tool": tool, "params": params or {}}
17
+ )
18
+ return response.json()
19
+
20
+ def validate_step(step_name, validation_func):
21
+ """Run a validation step and report results"""
22
+ print(f"Validating: {step_name}...", end=" ")
23
+ try:
24
+ result = validation_func()
25
+ if result:
26
+ print("✅ PASSED")
27
+ return True
28
+ else:
29
+ print("❌ FAILED")
30
+ return False
31
+ except Exception as e:
32
+ print(f"❌ ERROR: {e}")
33
+ return False
34
+
35
+ def check_neo4j():
36
+ """Check Neo4j is accessible via MCP"""
37
+ result = call_mcp("get_schema")
38
+ return "labels" in result
39
+
40
+ def check_postgres():
41
+ """Check PostgreSQL has sample data"""
42
+ result = call_mcp("query_postgres", {"query": "SELECT COUNT(*) as count FROM customers"})
43
+ return result.get("data", [{}])[0].get("count", 0) > 0
44
+
45
+ def check_schema_discovery():
46
+ """Check schema can be discovered"""
47
+ result = call_mcp("discover_postgres_schema")
48
+ schema = result.get("schema", {})
49
+ return "customers" in schema and "orders" in schema
50
+
51
+ def create_test_workflow():
52
+ """Create a test workflow"""
53
+ # Create workflow
54
+ workflow = call_mcp("write_graph", {
55
+ "action": "create_node",
56
+ "label": "Workflow",
57
+ "properties": {
58
+ "id": "validation-workflow",
59
+ "name": "Validation Test",
60
+ "status": "active"
61
+ }
62
+ })
63
+
64
+ # Create test instruction
65
+ instruction = call_mcp("write_graph", {
66
+ "action": "create_node",
67
+ "label": "Instruction",
68
+ "properties": {
69
+ "id": "validation-inst-1",
70
+ "type": "generate_sql",
71
+ "sequence": 1,
72
+ "status": "pending",
73
+ "pause_duration": 5, # Short pause for testing
74
+ "parameters": json.dumps({"question": "Count all customers"})
75
+ }
76
+ })
77
+
78
+ # Link instruction to workflow
79
+ call_mcp("query_graph", {
80
+ "query": """
81
+ MATCH (w:Workflow {id: 'validation-workflow'}),
82
+ (i:Instruction {id: 'validation-inst-1'})
83
+ CREATE (w)-[:HAS_INSTRUCTION]->(i)
84
+ """
85
+ })
86
+
87
+ return workflow.get("created") is not None
88
+
89
+ def check_instruction_execution():
90
+ """Check if instruction gets executed"""
91
+ # Wait for agent to pick it up (max 60 seconds)
92
+ for _ in range(12):
93
+ result = call_mcp("query_graph", {
94
+ "query": """
95
+ MATCH (i:Instruction {id: 'validation-inst-1'})
96
+ RETURN i.status as status
97
+ """
98
+ })
99
+
100
+ status = result["data"][0]["status"] if result.get("data") else "unknown"
101
+
102
+ if status in ["executing", "complete"]:
103
+ return True
104
+
105
+ time.sleep(5)
106
+
107
+ return False
108
+
109
+ def check_execution_logged():
110
+ """Check if execution was logged"""
111
+ result = call_mcp("query_graph", {
112
+ "query": """
113
+ MATCH (i:Instruction {id: 'validation-inst-1'})-[:EXECUTED_AS]->(e:Execution)
114
+ RETURN e
115
+ """
116
+ })
117
+
118
+ return len(result.get("data", [])) > 0
119
+
120
+ def check_frontend():
121
+ """Check if frontend is accessible"""
122
+ try:
123
+ response = requests.get("http://localhost:3000")
124
+ return response.status_code == 200
125
+ except:
126
+ return False
127
+
128
+ def main():
129
+ print("=" * 50)
130
+ print("MVP SYSTEM VALIDATION")
131
+ print("=" * 50)
132
+ print()
133
+
134
+ # Track results
135
+ all_passed = True
136
+
137
+ # Core services
138
+ all_passed &= validate_step("Neo4j accessible via MCP", check_neo4j)
139
+ all_passed &= validate_step("PostgreSQL has sample data", check_postgres)
140
+ all_passed &= validate_step("Frontend is accessible", check_frontend)
141
+
142
+ # Functionality
143
+ all_passed &= validate_step("Schema discovery works", check_schema_discovery)
144
+ all_passed &= validate_step("Workflow creation works", create_test_workflow)
145
+
146
+ print()
147
+ print("Waiting for agent to process instruction...")
148
+ all_passed &= validate_step("Instruction gets executed", check_instruction_execution)
149
+ all_passed &= validate_step("Execution is logged", check_execution_logged)
150
+
151
+ # Final verification
152
+ print()
153
+ print("=" * 50)
154
+ if all_passed:
155
+ print("✅ ALL VALIDATIONS PASSED!")
156
+ print("The MVP system is working correctly.")
157
+
158
+ # Show sample query result
159
+ result = call_mcp("query_graph", {
160
+ "query": """
161
+ MATCH (n)
162
+ RETURN labels(n)[0] as label, count(n) as count
163
+ ORDER BY count DESC
164
+ """
165
+ })
166
+
167
+ print()
168
+ print("Graph Statistics:")
169
+ for item in result.get("data", []):
170
+ print(f" - {item['label']}: {item['count']} nodes")
171
+
172
+ else:
173
+ print("❌ SOME VALIDATIONS FAILED")
174
+ print("Please check the logs and fix issues.")
175
+ sys.exit(1)
176
+
177
+ print("=" * 50)
178
+
179
+ if __name__ == "__main__":
180
+ main()