- Add GNS-2 label taxonomy (66 labels) with semantic routing - Tier 2 agents (capability-analyst, agent-architect, evaluator) enabled for self-cascade - GNS agent protocol: checkpoint v2 in issue body, machine-readable event footers - GiteaClient extended: checkpoint CRUD, event parsing, assignee/lock control, triggered issue polling - PipelineRunner rewritten as PollingSupervisor: reactive instead of active dispatch - Security: circuit breakers (is_locked), budget governance, depth limits - Scripts: init-gns-labels.py, validate-gns-agents.py - Milestone #67 + 7 phase issues (#99-#105) tracking evolution Refs: Milestone #67, Issues #99-#105
118 lines
5.9 KiB
Python
118 lines
5.9 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
GNS-2 Label Initialization Script
|
|
Idempotent creation of Gitea labels for GNS-2 semantic routing.
|
|
"""
|
|
import urllib.request
|
|
import json
|
|
import os
|
|
|
|
GITEA_API = os.environ.get('GITEA_API_URL', 'https://git.softuniq.eu/api/v1')
|
|
REPO = 'UniqueSoft/APAW'
|
|
USER = 'NW'
|
|
PASS = 'eshkink0t'
|
|
|
|
def api(path, data=None, method='GET'):
|
|
url = f"{GITEA_API}/repos/{REPO}{path}"
|
|
headers = {'Content-Type': 'application/json'}
|
|
req = urllib.request.Request(
|
|
url,
|
|
data=json.dumps(data).encode() if data else None,
|
|
headers=headers,
|
|
method=method
|
|
)
|
|
# Basic Auth
|
|
import base64
|
|
creds = base64.b64encode(f"{USER}:{PASS}".encode()).decode()
|
|
req.add_header('Authorization', f'Basic {creds}')
|
|
try:
|
|
with urllib.request.urlopen(req) as r:
|
|
return json.loads(r.read())
|
|
except urllib.error.HTTPError as e:
|
|
body = e.read().decode()
|
|
print(f" HTTP {e.code}: {body}")
|
|
return None
|
|
|
|
LABELS = [
|
|
# Phase labels
|
|
{"name": "phase::gathering-evidence", "color": "c2e0c6", "description": "Agent is gathering data"},
|
|
{"name": "phase::drafting-spec", "color": "0052cc", "description": "Agent is drafting specification"},
|
|
{"name": "phase::refining-prompt", "color": "fbca04", "description": "Agent is refining prompts"},
|
|
{"name": "phase::awaiting-review", "color": "d93f0b", "description": "Agent awaits review"},
|
|
{"name": "phase::executing", "color": "0e8a16", "description": "Agent is executing task"},
|
|
{"name": "phase::verifying", "color": "5319e7", "description": "Agent is verifying results"},
|
|
# Agent labels
|
|
{"name": "agent::orchestrator", "color": "7C3AED", "description": "Owned by orchestrator"},
|
|
{"name": "agent::capability-analyst", "color": "6366F1", "description": "Owned by capability-analyst"},
|
|
{"name": "agent::agent-architect", "color": "10B981", "description": "Owned by agent-architect"},
|
|
{"name": "agent::lead-developer", "color": "DC2626", "description": "Owned by lead-developer"},
|
|
{"name": "agent::code-skeptic", "color": "059669", "description": "Owned by code-skeptic"},
|
|
{"name": "agent::the-fixer", "color": "D97706", "description": "Owned by the-fixer"},
|
|
{"name": "agent::evaluator", "color": "8B5CF6", "description": "Owned by evaluator"},
|
|
{"name": "agent::history-miner", "color": "6B7280", "description": "Owned by history-miner"},
|
|
{"name": "agent::system-analyst", "color": "2563EB", "description": "Owned by system-analyst"},
|
|
{"name": "agent::sdet-engineer", "color": "0891B2", "description": "Owned by sdet-engineer"},
|
|
# Budget labels
|
|
{"name": "budget::sufficient", "color": "0e8a16", "description": "Token budget sufficient"},
|
|
{"name": "budget::warning", "color": "fbca04", "description": "Token budget low"},
|
|
{"name": "budget::exhausted", "color": "b60205", "description": "Token budget exhausted"},
|
|
# Permission labels
|
|
{"name": "permission::read-only", "color": "cfd3d7", "description": "Read-only access"},
|
|
{"name": "permission::write-code", "color": "0052cc", "description": "Can write code"},
|
|
{"name": "permission::write-config", "color": "5319e7", "description": "Can write config"},
|
|
{"name": "permission::evolve-system", "color": "b60205", "description": "Can evolve system"},
|
|
{"name": "permission::violation", "color": "b60205", "description": "Security violation"},
|
|
# Cascade labels
|
|
{"name": "cascade::depth-0", "color": "cfd3d7", "description": "No subagent calls"},
|
|
{"name": "cascade::depth-1", "color": "c2e0c6", "description": "1-level subagent calls"},
|
|
{"name": "cascade::depth-2", "color": "0052cc", "description": "2-level subagent calls"},
|
|
{"name": "cascade::depth-n", "color": "5319e7", "description": "Unlimited subagent calls"},
|
|
{"name": "cascade::depth-exceeded", "color": "b60205", "description": "Depth limit exceeded"},
|
|
# Quality labels
|
|
{"name": "quality::pass", "color": "0e8a16", "description": "Quality check passed"},
|
|
{"name": "quality::fail", "color": "b60205", "description": "Quality check failed"},
|
|
{"name": "quality::needs-fix", "color": "fbca04", "description": "Needs fixes"},
|
|
{"name": "quality::blocked", "color": "d73a4a", "description": "Blocked by quality"},
|
|
# Evolution labels
|
|
{"name": "evolution::model-change", "color": "8B5CF6", "description": "Model change evolution"},
|
|
{"name": "evolution::new-agent", "color": "10B981", "description": "New agent evolution"},
|
|
{"name": "evolution::new-skill", "color": "2563EB", "description": "New skill evolution"},
|
|
{"name": "evolution::new-workflow", "color": "7C3AED", "description": "New workflow evolution"},
|
|
{"name": "evolution::prompt-opt", "color": "D97706", "description": "Prompt optimization evolution"},
|
|
# Memory labels
|
|
{"name": "memory::checkpoint", "color": "0052cc", "description": "Checkpoint stored"},
|
|
{"name": "memory::stale", "color": "fbca04", "description": "Checkpoint stale"},
|
|
{"name": "memory::fresh", "color": "0e8a16", "description": "Checkpoint fresh"},
|
|
{"name": "memory::recoverable", "color": "c2e0c6", "description": "Checkpoint recoverable"},
|
|
]
|
|
|
|
def main():
|
|
print("GNS-2 Label Initialization")
|
|
print(f"Target: {REPO}")
|
|
print()
|
|
|
|
existing = api("/labels")
|
|
existing_names = {l['name'] for l in (existing or [])}
|
|
print(f"Existing labels: {len(existing_names)}")
|
|
|
|
created = 0
|
|
skipped = 0
|
|
for label in LABELS:
|
|
if label['name'] in existing_names:
|
|
print(f" SKIP: {label['name']}")
|
|
skipped += 1
|
|
continue
|
|
result = api("/labels", label, 'POST')
|
|
if result:
|
|
print(f" CREATE: {label['name']} ({label['color']})")
|
|
created += 1
|
|
else:
|
|
print(f" FAIL: {label['name']}")
|
|
|
|
print()
|
|
print(f"Done: {created} created, {skipped} skipped")
|
|
print(f"Total labels: {len(existing_names) + created}")
|
|
|
|
if __name__ == '__main__':
|
|
main()
|