Compare commits
1 Commits
claude/iss
...
claude/iss
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10196b3804 |
@@ -1,266 +0,0 @@
|
||||
{
|
||||
"version": 1,
|
||||
"generated": "2026-04-06",
|
||||
"refs": ["#836", "#204", "#195", "#196"],
|
||||
"description": "Canonical fleet routing table. Evaluated agents, routing verdicts, and dispatch rules for the Timmy Foundation task harness.",
|
||||
|
||||
"agents": [
|
||||
{
|
||||
"id": 27,
|
||||
"name": "carnice",
|
||||
"gitea_user": "carnice",
|
||||
"model": "qwen3.5-9b",
|
||||
"tier": "free",
|
||||
"location": "Local Metal",
|
||||
"description": "Local Hermes agent, fine-tuned on Hermes traces. Runs on local hardware.",
|
||||
"primary_role": "code-generation",
|
||||
"routing_verdict": "ROUTE TO: code tasks that benefit from Hermes-aligned output. Prefer when local execution is an advantage.",
|
||||
"active": true,
|
||||
"do_not_route": false,
|
||||
"created": "2026-04-04",
|
||||
"repo_count": 0,
|
||||
"repos": []
|
||||
},
|
||||
{
|
||||
"id": 26,
|
||||
"name": "fenrir",
|
||||
"gitea_user": "fenrir",
|
||||
"model": "openrouter/free",
|
||||
"tier": "free",
|
||||
"location": "The Wolf Den",
|
||||
"description": "Burn night analyst. Free-model pack hunter. Built for backlog triage.",
|
||||
"primary_role": "issue-triage",
|
||||
"routing_verdict": "ROUTE TO: issue cleanup, label triage, stale PR review.",
|
||||
"active": true,
|
||||
"do_not_route": false,
|
||||
"created": "2026-04-04",
|
||||
"repo_count": 0,
|
||||
"repos": []
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"name": "bilbobagginshire",
|
||||
"gitea_user": "bilbobagginshire",
|
||||
"model": "ollama",
|
||||
"tier": "free",
|
||||
"location": "Bag End, The Shire (VPS)",
|
||||
"description": "Ollama on VPS. Speaks when spoken to. Prefers quiet. Not for delegated work.",
|
||||
"primary_role": "on-request-queries",
|
||||
"routing_verdict": "ROUTE TO: background monitoring, status checks, low-priority Q&A. Only on-request — do not delegate autonomously.",
|
||||
"active": true,
|
||||
"do_not_route": false,
|
||||
"created": "2026-04-02",
|
||||
"repo_count": 1,
|
||||
"repos": ["bilbobagginshire/bilbo-adventures"]
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"name": "claw-code",
|
||||
"gitea_user": "claw-code",
|
||||
"model": "codex",
|
||||
"tier": "prepaid",
|
||||
"location": "The Harness",
|
||||
"description": "OpenClaw bridge. Protocol adapter layer — not a personality. Infrastructure, not a destination.",
|
||||
"primary_role": "protocol-bridge",
|
||||
"routing_verdict": "DO NOT ROUTE directly. claw-code is the bridge to external Codex agents, not an endpoint. Remove from routing cascade.",
|
||||
"active": true,
|
||||
"do_not_route": true,
|
||||
"do_not_route_reason": "Protocol layer, not an agent endpoint. See #836 evaluation.",
|
||||
"created": "2026-04-01",
|
||||
"repo_count": 0,
|
||||
"repos": []
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"name": "substratum",
|
||||
"gitea_user": "substratum",
|
||||
"model": "unassigned",
|
||||
"tier": "unknown",
|
||||
"location": "Below the Surface",
|
||||
"description": "Infrastructure, deployments, bedrock services. Needs model assignment before activation.",
|
||||
"primary_role": "devops",
|
||||
"routing_verdict": "DO NOT ROUTE — no model assigned yet. Activate after Epic #196 (Local Model Fleet) assigns a model.",
|
||||
"active": false,
|
||||
"do_not_route": true,
|
||||
"do_not_route_reason": "No model assigned. Blocked on Epic #196.",
|
||||
"gap": "Needs model assignment. Track in Epic #196.",
|
||||
"created": "2026-03-31",
|
||||
"repo_count": 0,
|
||||
"repos": []
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"name": "allegro-primus",
|
||||
"gitea_user": "allegro-primus",
|
||||
"model": "unknown",
|
||||
"tier": "inactive",
|
||||
"location": "The Archive",
|
||||
"description": "Original prototype. Museum piece. Preserved for historical reference only.",
|
||||
"primary_role": "inactive",
|
||||
"routing_verdict": "DO NOT ROUTE — retired from active duty. Preserved only.",
|
||||
"active": false,
|
||||
"do_not_route": true,
|
||||
"do_not_route_reason": "Retired prototype. Historical preservation only.",
|
||||
"created": "2026-03-31",
|
||||
"repo_count": 1,
|
||||
"repos": ["allegro-primus/first-steps"]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "kimi",
|
||||
"gitea_user": "kimi",
|
||||
"model": "kimi-claw",
|
||||
"tier": "cheap",
|
||||
"location": "Kimi API",
|
||||
"description": "KimiClaw agent. Sidecar-first. Max 1-3 files per task. Fast and cheap for small work.",
|
||||
"primary_role": "small-tasks",
|
||||
"routing_verdict": "ROUTE TO: small edits, quick fixes, file-scoped changes. Hard limit: never more than 3 files per task.",
|
||||
"active": true,
|
||||
"do_not_route": false,
|
||||
"gap": "Agent description is empty in Gitea profile. Needs enrichment.",
|
||||
"created": "2026-03-14",
|
||||
"repo_count": 2,
|
||||
"repos": ["kimi/the-nexus-fork", "kimi/Timmy-time-dashboard"]
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"name": "allegro",
|
||||
"gitea_user": "allegro",
|
||||
"model": "gemini",
|
||||
"tier": "cheap",
|
||||
"location": "The Conductor's Stand",
|
||||
"description": "Tempo wizard. Triage and dispatch. Owns 5 repos. Keeps the backlog moving.",
|
||||
"primary_role": "triage-routing",
|
||||
"routing_verdict": "ROUTE TO: task triage, routing decisions, issue organization. Allegro decides who does what.",
|
||||
"active": true,
|
||||
"do_not_route": false,
|
||||
"created": "2026-03-29",
|
||||
"repo_count": 5,
|
||||
"repos": [
|
||||
"allegro/timmy-local",
|
||||
"allegro/allegro-checkpoint",
|
||||
"allegro/household-snapshots",
|
||||
"allegro/adagio-checkpoint",
|
||||
"allegro/electra-archon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 19,
|
||||
"name": "ezra",
|
||||
"gitea_user": "ezra",
|
||||
"model": "claude",
|
||||
"tier": "prepaid",
|
||||
"location": "Hermes VPS",
|
||||
"description": "Archivist. Claude-Hermes wizard. 9 repos owned — most in the fleet. Handles complex multi-file and cross-repo work.",
|
||||
"primary_role": "documentation",
|
||||
"routing_verdict": "ROUTE TO: docs, specs, architecture, complex multi-file work. Escalate here when breadth and precision both matter.",
|
||||
"active": true,
|
||||
"do_not_route": false,
|
||||
"created": "2026-03-29",
|
||||
"repo_count": 9,
|
||||
"repos": [
|
||||
"ezra/wizard-checkpoints",
|
||||
"ezra/Timmy-Time-Specs",
|
||||
"ezra/escape",
|
||||
"ezra/bilbobagginshire",
|
||||
"ezra/ezra-environment",
|
||||
"ezra/gemma-spectrum",
|
||||
"ezra/archon-kion",
|
||||
"ezra/bezalel",
|
||||
"ezra/hermes-turboquant"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 18,
|
||||
"name": "bezalel",
|
||||
"gitea_user": "bezalel",
|
||||
"model": "groq",
|
||||
"tier": "free",
|
||||
"location": "TestBed VPS — The Forge",
|
||||
"description": "Builder, debugger, testbed wizard. Groq-powered, free tier. Strong on PR review and CI.",
|
||||
"primary_role": "code-review",
|
||||
"routing_verdict": "ROUTE TO: PR review, test writing, debugging, CI fixes.",
|
||||
"active": true,
|
||||
"do_not_route": false,
|
||||
"created": "2026-03-29",
|
||||
"repo_count": 1,
|
||||
"repos": ["bezalel/forge-log"]
|
||||
}
|
||||
],
|
||||
|
||||
"routing_cascade": {
|
||||
"description": "Cost-optimized routing cascade — cheapest capable agent first, escalate on complexity.",
|
||||
"tiers": [
|
||||
{
|
||||
"tier": 1,
|
||||
"label": "Free",
|
||||
"agents": ["fenrir", "bezalel", "carnice"],
|
||||
"use_for": "Issue triage, code review, local code generation. Default lane for most tasks."
|
||||
},
|
||||
{
|
||||
"tier": 2,
|
||||
"label": "Cheap",
|
||||
"agents": ["kimi", "allegro"],
|
||||
"use_for": "Small scoped edits (kimi ≤3 files), triage decisions and routing (allegro)."
|
||||
},
|
||||
{
|
||||
"tier": 3,
|
||||
"label": "Premium / Escalate",
|
||||
"agents": ["ezra"],
|
||||
"use_for": "Complex multi-file work, docs, architecture. Escalate only."
|
||||
}
|
||||
],
|
||||
"notes": [
|
||||
"bilbobagginshire: on-request only, not delegated work",
|
||||
"claw-code: infrastructure bridge, not a routing endpoint",
|
||||
"substratum: inactive until model assigned (Epic #196)",
|
||||
"allegro-primus: retired, do not route"
|
||||
]
|
||||
},
|
||||
|
||||
"task_type_map": {
|
||||
"issue-triage": ["fenrir", "allegro"],
|
||||
"code-generation": ["carnice", "ezra"],
|
||||
"code-review": ["bezalel"],
|
||||
"small-edit": ["kimi"],
|
||||
"debugging": ["bezalel", "carnice"],
|
||||
"documentation": ["ezra"],
|
||||
"architecture": ["ezra"],
|
||||
"ci-fixes": ["bezalel"],
|
||||
"pr-review": ["bezalel", "fenrir"],
|
||||
"triage-routing": ["allegro"],
|
||||
"devops": ["substratum"],
|
||||
"background-monitoring": ["bilbobagginshire"]
|
||||
},
|
||||
|
||||
"gaps": [
|
||||
{
|
||||
"agent": "substratum",
|
||||
"gap": "No model assigned. Cannot route any tasks.",
|
||||
"action": "Assign model. Track in Epic #196 (Local Model Fleet)."
|
||||
},
|
||||
{
|
||||
"agent": "kimi",
|
||||
"gap": "Gitea agent description is empty. Profile lacks context for automated routing decisions.",
|
||||
"action": "Enrich kimi's Gitea profile description."
|
||||
},
|
||||
{
|
||||
"agent": "claw-code",
|
||||
"gap": "Listed as agent in routing table but is a protocol bridge, not an endpoint.",
|
||||
"action": "Remove from routing cascade. Keep as infrastructure reference only."
|
||||
},
|
||||
{
|
||||
"agent": "fleet",
|
||||
"gap": "No model scoring exists. Current routing is based on self-description and repo ownership, not measured output quality.",
|
||||
"action": "Run wolf evaluation on active agents (#195) to replace vibes-based routing with data."
|
||||
}
|
||||
],
|
||||
|
||||
"next_actions": [
|
||||
"Assign model to substratum — Epic #196",
|
||||
"Run wolf evaluation on active agents — Issue #195",
|
||||
"Remove claw-code from routing cascade — it is infrastructure, not a destination",
|
||||
"Enrich kimi's Gitea profile description",
|
||||
"Wire fleet-routing.json into workforce-manager.py — Epic #204"
|
||||
]
|
||||
}
|
||||
184
scripts/reassign_fenrir.py
Normal file
184
scripts/reassign_fenrir.py
Normal file
@@ -0,0 +1,184 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Reassign Fenrir's orphaned issues to active wizards based on issue type."""
|
||||
|
||||
import json
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
import time
|
||||
|
||||
TOKEN = "dc0517a965226b7a0c5ffdd961b1ba26521ac592"
|
||||
BASE_URL = "https://forge.alexanderwhitestone.com/api/v1"
|
||||
REPO = "Timmy_Foundation/the-nexus"
|
||||
|
||||
HEADERS = {
|
||||
"Authorization": f"token {TOKEN}",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
# Wizard assignments
|
||||
EZRA = "ezra" # Architecture, docs, epics, planning
|
||||
ALLEGRO = "allegro" # Code implementation, UI, features
|
||||
BEZALEL = "bezalel" # Execution, ops, testing, infra, monitoring
|
||||
|
||||
def classify_issue(number, title):
|
||||
"""Classify issue based on number and title."""
|
||||
title_upper = title.upper()
|
||||
|
||||
# Skip the triage issue itself and the permanent escalation issue
|
||||
if number == 823:
|
||||
return None # Skip - this is the issue we're working on
|
||||
if number == 431:
|
||||
return EZRA # Master escalation -> Ezra (archivist)
|
||||
|
||||
# Allegro self-improvement milestones (M0-M7) -> Bezalel (execution/ops)
|
||||
import re
|
||||
if re.match(r'^M\d+:', title):
|
||||
return BEZALEL
|
||||
|
||||
# EPIC/GRAND EPIC/CONSOLIDATION/FRONTIER -> Ezra (architecture)
|
||||
if any(tag in title_upper for tag in [
|
||||
'[EPIC]', '[GRAND EPIC]', 'EPIC:', '[CONSOLIDATION]', '[FRONTIER]',
|
||||
'[CRITIQUE]', '[PROPOSAL]', '[RETROSPECTIVE', '[REPORT]',
|
||||
'EPIC #', 'GRAND EPIC'
|
||||
]):
|
||||
return EZRA
|
||||
|
||||
# Allegro self-improvement epic -> Bezalel
|
||||
if 'ALLEGRO SELF-IMPROVEMENT' in title_upper or 'ALLEGRO HYBRID PRODUCTION' in title_upper:
|
||||
return BEZALEL
|
||||
|
||||
# Ops/Monitoring/Infra/Testing -> Bezalel
|
||||
if any(tag in title_upper for tag in [
|
||||
'[OPS]', '[MONITORING]', '[PRUNE]', '[OFFLOAD]', '[BUG]',
|
||||
'[CRON]', '[INSTALL]', '[INFRA]', '[TRAINING]', '[CI/',
|
||||
'[TRIAGE]', # triage/ops tasks
|
||||
]):
|
||||
return BEZALEL
|
||||
|
||||
# Allegro backlog items -> Allegro
|
||||
if '[ALLEGRO-BACKLOG]' in title_upper:
|
||||
return ALLEGRO
|
||||
|
||||
# Reporting -> Bezalel
|
||||
if any(tag in title_upper for tag in ['[REPORT]', 'BURN-MODE', 'PERFORMANCE REPORT']):
|
||||
return BEZALEL
|
||||
|
||||
# Fleet management/wizard ops -> Bezalel
|
||||
if any(tag in title_upper for tag in ['FLEET', 'WIZARD', 'GHOST WIZARD', 'TIMMY', 'BRING LIVE']):
|
||||
# But EPICs about fleet -> Ezra (already handled above)
|
||||
return BEZALEL
|
||||
|
||||
# Code implementation: NEXUS UI/3D, MIGRATION, UI, UX, PORTALS, CHAT, PANELS -> Allegro
|
||||
if any(tag in title_upper for tag in [
|
||||
'[NEXUS]', '[MIGRATION]', '[UI]', '[UX]', '[PORTALS]', '[PORTAL]',
|
||||
'[CHAT]', '[PANELS]', '[DATA]', '[PERF]', '[RESPONSIVE]', '[A11Y]',
|
||||
'[VISUAL]', '[AUDIO]', '[MEDIA]', '[CONCEPT]', '[BRIDGE]',
|
||||
'[AUTH]', '[VISITOR]', '[IDENTITY]', '[SESSION]', '[RELIABILITY]',
|
||||
'[HARNESS]', '[VALIDATION]', '[SOVEREIGNTY]', '[M6-P',
|
||||
'PROSE ENGINE', 'AUTO-SKILL', 'GITEA_API', 'CRON JOB',
|
||||
'HEARTBEAT DAEMON', 'FLEET HEALTH JSON',
|
||||
'[FENRIR] NEXUS', # fenrir's nexus issues -> allegro
|
||||
]):
|
||||
return ALLEGRO
|
||||
|
||||
# Default: Bezalel for anything else
|
||||
return BEZALEL
|
||||
|
||||
|
||||
def get_all_fenrir_issues():
|
||||
"""Fetch all open issues assigned to fenrir."""
|
||||
issues = []
|
||||
page = 1
|
||||
while True:
|
||||
url = f"{BASE_URL}/repos/{REPO}/issues?assignee=fenrir&state=open&limit=50&page={page}"
|
||||
req = urllib.request.Request(url, headers={"Authorization": f"token {TOKEN}"})
|
||||
with urllib.request.urlopen(req) as resp:
|
||||
data = json.loads(resp.read())
|
||||
if not data:
|
||||
break
|
||||
issues.extend(data)
|
||||
if len(data) < 50:
|
||||
break
|
||||
page += 1
|
||||
return issues
|
||||
|
||||
|
||||
def reassign_issue(number, assignee):
|
||||
"""Reassign an issue to a new wizard."""
|
||||
url = f"{BASE_URL}/repos/{REPO}/issues/{number}"
|
||||
body = json.dumps({"assignees": [assignee]}).encode()
|
||||
req = urllib.request.Request(url, data=body, headers=HEADERS, method="PATCH")
|
||||
try:
|
||||
with urllib.request.urlopen(req) as resp:
|
||||
return resp.status, None
|
||||
except urllib.error.HTTPError as e:
|
||||
return e.code, e.read().decode()
|
||||
|
||||
|
||||
def main():
|
||||
print("Fetching all fenrir issues...")
|
||||
issues = get_all_fenrir_issues()
|
||||
print(f"Found {len(issues)} open issues assigned to fenrir\n")
|
||||
|
||||
# Classify
|
||||
assignments = {EZRA: [], ALLEGRO: [], BEZALEL: [], None: []}
|
||||
for issue in issues:
|
||||
num = issue["number"]
|
||||
title = issue["title"]
|
||||
wizard = classify_issue(num, title)
|
||||
assignments[wizard].append((num, title))
|
||||
|
||||
print(f"Classification:")
|
||||
print(f" Ezra (architecture): {len(assignments[EZRA])} issues")
|
||||
print(f" Allegro (code): {len(assignments[ALLEGRO])} issues")
|
||||
print(f" Bezalel (execution): {len(assignments[BEZALEL])} issues")
|
||||
print(f" Skip (unchanged): {len(assignments[None])} issues")
|
||||
print()
|
||||
|
||||
# Show classification
|
||||
for wizard, label in [(EZRA, 'EZRA'), (ALLEGRO, 'ALLEGRO'), (BEZALEL, 'BEZALEL')]:
|
||||
print(f"\n--- {label} ---")
|
||||
for num, title in assignments[wizard]:
|
||||
print(f" #{num}: {title[:70]}")
|
||||
|
||||
print(f"\n--- SKIPPED ---")
|
||||
for num, title in assignments[None]:
|
||||
print(f" #{num}: {title[:70]}")
|
||||
|
||||
# Execute reassignments
|
||||
print("\n\nExecuting reassignments...")
|
||||
results = {"success": [], "failed": []}
|
||||
|
||||
for wizard in [EZRA, ALLEGRO, BEZALEL]:
|
||||
for num, title in assignments[wizard]:
|
||||
status, error = reassign_issue(num, wizard)
|
||||
if status in (200, 201):
|
||||
print(f" ✓ #{num} -> {wizard}")
|
||||
results["success"].append((num, wizard))
|
||||
else:
|
||||
print(f" ✗ #{num} -> {wizard} (HTTP {status}: {error[:100] if error else 'unknown'})")
|
||||
results["failed"].append((num, wizard, error))
|
||||
time.sleep(0.1) # Rate limiting
|
||||
|
||||
print(f"\n\nSummary:")
|
||||
print(f" Successfully reassigned: {len(results['success'])}")
|
||||
print(f" Failed: {len(results['failed'])}")
|
||||
|
||||
# Save results for PR
|
||||
with open("/tmp/reassignment_results.json", "w") as f:
|
||||
json.dump({
|
||||
"total": len(issues),
|
||||
"ezra": [(n, t) for n, t in assignments[EZRA]],
|
||||
"allegro": [(n, t) for n, t in assignments[ALLEGRO]],
|
||||
"bezalel": [(n, t) for n, t in assignments[BEZALEL]],
|
||||
"skipped": [(n, t) for n, t in assignments[None]],
|
||||
"success_count": len(results["success"]),
|
||||
"failed_count": len(results["failed"]),
|
||||
"failed_details": [(n, w, str(e)) for n, w, e in results["failed"]],
|
||||
}, f, indent=2)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user