#!/usr/bin/env python3 """GNS-2 End-to-End Integration Test""" import urllib.request import json import base64 import time import sys USER, PASS, REPO, ISSUE = 'NW', 'eshkink0t', 'UniqueSoft/APAW', 110 class GiteaAPI: def __init__(self): self.base = 'https://git.softuniq.eu/api/v1' self.creds = base64.b64encode(f"{USER}:{PASS}".encode()).decode() def api(self, path, data=None, method='GET'): url = f"{self.base}/repos/{REPO}{path}" req = urllib.request.Request( url, data=json.dumps(data).encode() if data else None, headers={'Content-Type': 'application/json'}, method=method) req.add_header('Authorization', f'Basic {self.creds}') with urllib.request.urlopen(req) as r: return json.loads(r.read()) if r.status != 204 else None gitea = GiteaAPI() def update_checkpoint(phase, depth, consumed, remaining, last_agent, next_agent, history_append): issue = gitea.api(f"/issues/{ISSUE}") body = issue['body'] checkpoint_yaml = ( f"checkpoint:\n version: 2\n issue: {ISSUE}\n phase: {phase}\n" f" depth: {depth}\n last_agent: {last_agent}\n" f" last_invocation: {last_agent}-110-{int(time.time())}\n" f" budget:\n total: 8000\n consumed: {consumed}\n" f" remaining: {remaining}\n state:\n" f" labels: [status::{phase}, budget::{'sufficient' if remaining > 2000 else 'warning' if remaining > 0 else 'exhausted'}, cascade::depth-{depth}]\n" f" assignee: {next_agent}\n milestone: 67\n history:\n" f" - {{agent: orchestrator, invocation: orch-110-001, action: create_e2e_test}}\n{history_append}\n" f" next_agent: {next_agent}\n next_estimated_tokens: 1000\n" f" created_at: {time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())}\n") import re new_body = re.sub( r'## GNS Checkpoint\s*```yaml\s*[\s\S]*?```', f"## GNS Checkpoint\n```yaml\n{checkpoint_yaml}```", body) gitea.api(f"/issues/{ISSUE}", {"body": new_body}, 'PATCH') def post_comment(agent, evtype, depth, consumed, remaining, next_agent, extras=""): inv = int(time.time()) comment = ( f"## šŸ”„ {agent} | phase:executing | depth:{depth}\n\n" f"**Event Type**: {evtype}\n**Parent**: orch-110-001\n" f"**Invocation**: {agent}-110-{inv}\n" f"**Budget**: 8000 → {consumed} → {remaining}\n\n" f"### Action Taken\n{agent} processed checkpoint.\n\n" f"### Next Decision\n**Recommended next**: @{next_agent}\n" f"**Estimated tokens**: 1000\n**Budget remaining**: {remaining}\n\n{extras}\n---\n" f"") gitea.api(f"/issues/{ISSUE}/comments", {"body": comment}, 'POST') def add_label(label): try: gitea.api(f"/issues/{ISSUE}/labels", {"labels": [label]}, 'POST') except Exception as e: print(f" (Label {label}: {e})") def replace_scoped_label(scope, new_label): issue = gitea.api(f"/issues/{ISSUE}") for l in issue.get('labels', []): if l['name'].startswith(f"{scope}::"): try: gitea.api(f"/issues/{ISSUE}/labels/{l['id']}", method='DELETE') except Exception: pass add_label(new_label) def e2e_test(): print("="*60) print("GNS-2 End-to-End Test") print(f"Issue: #{ISSUE}") print("="*60) print("\n[1] Init...", end=' ') issue = gitea.api(f"/issues/{ISSUE}") print("OK") print("\n[2] Requirement Refiner...", end=' ') update_checkpoint('planned', 0, 500, 7500, 'requirement-refiner', 'capability-analyst', ' - {agent: req-refiner, invocation: req-110-001, action: refine}') post_comment('requirement-refiner', 'state_change', 0, 500, 7500, 'capability-analyst') replace_scoped_label('status', 'status::planned') add_label('agent::capability-analyst') print("OK") time.sleep(2) print("\n[3] Capability-Analyst spawns HistoryMiner (depth 0→1)...", end=' ') update_checkpoint('researching', 1, 1500, 6500, 'capability-analyst', 'history-miner', ' - {agent: cap-analyst, invocation: cap-110-001, action: subagent_call, target: history-miner}') cascade = "### Cascade Log\n| Agent | Task | Result | Tokens | Verdict |\n|-------|------|--------|--------|---------|\n| history-miner | git search | found 3 commits | 1000 | āœ… |" post_comment('capability-analyst', 'subagent_result', 1, 1500, 6500, 'agent-architect', cascade) replace_scoped_label('status', 'status::researching') add_label('cascade::depth-1') print("OK") time.sleep(2) print("\n[4] History Miner (Tier 0, leaf)...", end=' ') post_comment('history-miner', 'subagent_result', 1, 2500, 5500, 'agent-architect', "### Findings\n- Found `47b027a`\n- 2 related issues") print("OK") time.sleep(2) print("\n[5] Agent Architect completes spec (Tier 2, depth 1→2)...", end=' ') update_checkpoint('designed', 2, 3500, 4500, 'agent-architect', 'capability-analyst', ' - {agent: arch, invocation: arch-110-001, action: design_spec}') post_comment('agent-architect', 'subagent_result', 2, 3500, 4500, 'capability-analyst', "### Spec Designed\n- mcp-gitea-client.ts\n- docker-compose.yml") replace_scoped_label('status', 'status::designed') add_label('cascade::depth-2') print("OK") time.sleep(2) print("\n[6] Capability Analyst reviews and closes...", end=' ') update_checkpoint('completed', 2, 4000, 4000, 'capability-analyst', 'orchestrator', ' - {agent: cap-analyst, invocation: cap-110-002, action: review_complete}') post_comment('capability-analyst', 'state_change', 2, 4000, 4000, 'orchestrator', "### Review Complete\nāœ… All criteria met. Closing.") replace_scoped_label('status', 'status::done') add_label('budget::sufficient') add_label('quality::pass') gitea.api(f"/issues/{ISSUE}", {"state": "closed"}, 'PATCH') print("OK") # Verification issue = gitea.api(f"/issues/{ISSUE}") comments = gitea.api(f"/issues/{ISSUE}/comments") timeline = gitea.api(f"/issues/{ISSUE}/timeline") labels = [l['name'] for l in issue['labels']] print("\n"+"="*60+"\nVerification\n"+"="*60) print(f"State: {issue['state']}") print(f"Labels: {labels}") print(f"Comments: {len(comments)}, Timeline: {len(timeline)}") import re events = re.findall(r'', issue['body'] + '\n'.join(c['body'] for c in comments), re.DOTALL) print(f"GNS_EVENTs: {len(events)}") print(f"Checkpoint: {'āœ…' if '## GNS Checkpoint' in issue['body'] else 'āŒ'}") failures = [] if issue['state'] != 'closed': failures.append("Issue not closed") if len(events) < 5: failures.append(f"Too few events ({len(events)})") if 'status::done' not in labels: failures.append("No completed") if 'cascade::depth-2' not in labels: failures.append("No depth-2") if 'budget::sufficient' not in labels: failures.append("No budget") if 'quality::pass' not in labels: failures.append("No quality") if failures: print("\nāŒ FAILED") for f in failures: print(f" - {f}") return 1 print("\nāœ… ALL E2E TESTS PASSED\n"+"="*60) return 0 if __name__ == '__main__': sys.exit(e2e_test())