Fix supervisor monitoring with unique naming tags
ci.yml / Fix supervisor monitoring with unique naming tags (push) Failing after 0s
ci.yml / Fix supervisor monitoring with unique naming tags (push) Failing after 0s
Implement unique naming tags for all supervisors and workers to enable proper monitoring and management by the product-builder agent. The previous generic [CA-AUTO] prefix made it impossible to distinguish between different supervisor types and count their workers accurately. Changes: - Pool supervisors now use specific tags (AUTO-IMP-SUP, AUTO-REV-SUP, etc.) - Workers use corresponding tags (AUTO-IMP, AUTO-REV, etc.) - Singleton supervisors use unique tags (AUTO-ARCH, AUTO-EPIC, etc.) - Product-builder can now count supervisors/workers by tag pattern - Added metadata mapping for reliable supervisor re-launching - Updated system-watchdog to recognize new tag patterns This enables the product-builder to detect zombie supervisors, verify worker counts, and re-launch failed supervisors reliably.
This commit is contained in:
@@ -122,8 +122,8 @@ EXISTING_WORKERS = bash("curl -s ${SERVER}/session | python3 -c \"
|
||||
import sys, json
|
||||
for s in json.loads(sys.stdin.read()):
|
||||
title = s.get('title','')
|
||||
if title.startswith('[CA-AUTO] worker-hunt:'):
|
||||
module = title.replace('[CA-AUTO] worker-hunt: ','')
|
||||
if title.startswith('[AUTO-BUG] worker-hunt:'):
|
||||
module = title.replace('[AUTO-BUG] worker-hunt: ','')
|
||||
print(module + '=' + s['id'])
|
||||
\"", timeout=30000)
|
||||
|
||||
@@ -161,7 +161,7 @@ LOOP:
|
||||
for module in batch:
|
||||
SESSION_ID = bash("curl -s -X POST ${SERVER}/session \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{\"title\": \"[CA-AUTO] worker-hunt: <module>\"}' \
|
||||
-d '{\"title\": \"[AUTO-BUG] worker-hunt: <module>\"}' \
|
||||
| python3 -c \"import sys,json; print(json.loads(sys.stdin.read())['id'])\"",
|
||||
timeout=30000)
|
||||
bash("curl -s -X POST ${SERVER}/session/${SESSION_ID}/prompt_async \
|
||||
|
||||
@@ -256,7 +256,7 @@ LOOP FOREVER:
|
||||
# Create session
|
||||
SESSION_ID = bash("curl -s -X POST ${SERVER}/session \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{\"title\": \"[CA-AUTO] worker-review: PR-${pr.number}\"}' \
|
||||
-d '{\"title\": \"[AUTO-REV] worker-review: PR-${pr.number}\"}' \
|
||||
| python3 -c \"import sys,json; print(json.loads(sys.stdin.read())['id'])\"",
|
||||
timeout=30000)
|
||||
|
||||
|
||||
@@ -436,11 +436,28 @@ function audit_supervisor_health():
|
||||
# ── Step 1: Get all supervisor sessions ──────────────────────
|
||||
sessions = curl -s GET "${SERVER}/session" | parse JSON
|
||||
statuses = curl -s GET "${SERVER}/session/status" | parse JSON
|
||||
supervisor_sessions = [s for s in sessions
|
||||
if s.title.startswith("[CA-AUTO] supervisor:")]
|
||||
|
||||
# Map of supervisor tags to identify them
|
||||
supervisor_tags = [
|
||||
"AUTO-IMP-SUP", "AUTO-REV-SUP", "AUTO-UAT-SUP", "AUTO-BUG-SUP", "AUTO-INF-SUP",
|
||||
"AUTO-ARCH", "AUTO-EPIC", "AUTO-HUMAN", "AUTO-EVLV", "AUTO-GUARD",
|
||||
"AUTO-SPEC", "AUTO-BLOG", "AUTO-DOCS", "AUTO-TIME", "AUTO-OWNR", "AUTO-WDOG"
|
||||
]
|
||||
supervisor_sessions = []
|
||||
for s in sessions:
|
||||
for tag in supervisor_tags:
|
||||
if f"[{tag}]" in s.title:
|
||||
supervisor_sessions.append(s)
|
||||
break
|
||||
|
||||
for session in supervisor_sessions:
|
||||
name = session.title.replace("[CA-AUTO] supervisor: ", "")
|
||||
# Extract the display name from the title
|
||||
import re
|
||||
match = re.search(r'\[([A-Z-]+)\]\s+(.+)', session.title)
|
||||
if match:
|
||||
name = match.group(2) # The part after the tag
|
||||
else:
|
||||
name = session.title # Fallback
|
||||
session_status = statuses.get(session.id)
|
||||
|
||||
# Skip sessions that are completed/errored (product-builder handles those)
|
||||
@@ -549,8 +566,12 @@ function audit_supervisor_health():
|
||||
"human-liaison", "agent-evolver", "arch-guard", "spec-updater",
|
||||
"backlog-groomer", "docs-writer", "timeline-updater",
|
||||
"project-owner", "system-watchdog"]
|
||||
running_names = [s.title.replace("[CA-AUTO] supervisor: ", "")
|
||||
for s in supervisor_sessions]
|
||||
running_names = []
|
||||
for s in supervisor_sessions:
|
||||
# Extract display name from new tag format
|
||||
match = re.search(r'\[([A-Z-]+)\]\s+(.+)', s.title)
|
||||
if match:
|
||||
running_names.append(match.group(2))
|
||||
missing = [n for n in EXPECTED if n not in running_names]
|
||||
if missing:
|
||||
findings.append({
|
||||
@@ -703,9 +724,15 @@ function audit_session_spot_check():
|
||||
sessions = curl -s GET "${SERVER}/session" | parse JSON
|
||||
|
||||
# Find the 3 most recently active supervisor sessions
|
||||
active_supervisors = [s for s in sessions
|
||||
if s.title.startswith("[CA-AUTO]")
|
||||
and statuses.get(s.id) not in ("completed", "error")]
|
||||
supervisor_prefixes = ["[AUTO-IMP", "[AUTO-REV", "[AUTO-UAT", "[AUTO-BUG", "[AUTO-INF",
|
||||
"[AUTO-ARCH]", "[AUTO-EPIC]", "[AUTO-HUMAN]", "[AUTO-EVLV]",
|
||||
"[AUTO-GUARD]", "[AUTO-SPEC]", "[AUTO-BLOG]", "[AUTO-DOCS]",
|
||||
"[AUTO-TIME]", "[AUTO-OWNR]", "[AUTO-WDOG]"]
|
||||
active_supervisors = []
|
||||
for s in sessions:
|
||||
if any(s.title.startswith(prefix) for prefix in supervisor_prefixes):
|
||||
if statuses.get(s.id) not in ("completed", "error"):
|
||||
active_supervisors.append(s)
|
||||
# Sort by most recent activity (updatedAt or similar)
|
||||
recent_3 = active_supervisors[:3] # already sorted by update time
|
||||
|
||||
@@ -799,11 +826,26 @@ function audit_deep_session_introspection():
|
||||
session_summaries = {} # name -> { what_doing, health, issues }
|
||||
|
||||
sessions = curl -s GET "${SERVER}/session" | parse JSON
|
||||
supervisor_sessions = [s for s in sessions
|
||||
if s.title.startswith("[CA-AUTO] supervisor:")]
|
||||
# Find supervisor sessions by their unique tags
|
||||
supervisor_tags = [
|
||||
"AUTO-IMP-SUP", "AUTO-REV-SUP", "AUTO-UAT-SUP", "AUTO-BUG-SUP", "AUTO-INF-SUP",
|
||||
"AUTO-ARCH", "AUTO-EPIC", "AUTO-HUMAN", "AUTO-EVLV", "AUTO-GUARD",
|
||||
"AUTO-SPEC", "AUTO-BLOG", "AUTO-DOCS", "AUTO-TIME", "AUTO-OWNR", "AUTO-WDOG"
|
||||
]
|
||||
supervisor_sessions = []
|
||||
for s in sessions:
|
||||
for tag in supervisor_tags:
|
||||
if f"[{tag}]" in s.title:
|
||||
supervisor_sessions.append(s)
|
||||
break
|
||||
|
||||
for session in supervisor_sessions:
|
||||
name = session.title.replace("[CA-AUTO] supervisor: ", "")
|
||||
# Extract display name from the title
|
||||
match = re.search(r'\[([A-Z-]+)\]\s+(.+)', session.title)
|
||||
if match:
|
||||
name = match.group(2)
|
||||
else:
|
||||
name = session.title
|
||||
|
||||
# ── Read last 10 messages ────────────────────────────────
|
||||
messages = curl -s GET "${SERVER}/session/${session.id}/message?limit=10"
|
||||
@@ -994,7 +1036,12 @@ function audit_deep_session_introspection():
|
||||
issue_modifications = {} # issue_number -> [session_names]
|
||||
|
||||
for session in supervisor_sessions:
|
||||
name = session.title.replace("[CA-AUTO] supervisor: ", "")
|
||||
# Extract display name from the title
|
||||
match = re.search(r'\[([A-Z-]+)\]\s+(.+)', session.title)
|
||||
if match:
|
||||
name = match.group(2)
|
||||
else:
|
||||
name = session.title
|
||||
messages = curl -s GET "${SERVER}/session/${session.id}/message?limit=5"
|
||||
| parse JSON
|
||||
|
||||
@@ -1209,7 +1256,7 @@ function dispatch_one_off(agent_name, finding):
|
||||
# Create a session and dispatch via prompt_async
|
||||
SESSION_ID = curl -s -X POST "${SERVER}/session" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"title": "[CA-AUTO] one-off: <agent_name> — <finding.type>"}'
|
||||
-d '{"title": "[AUTO-ONEOFF] <agent_name> — <finding.type>"}'
|
||||
|
||||
curl -s -X POST "${SERVER}/session/${SESSION_ID}/prompt_async" \
|
||||
-H "Content-Type: application/json" \
|
||||
|
||||
@@ -163,8 +163,8 @@ EXISTING_WORKERS = bash("curl -s ${SERVER}/session | python3 -c \"
|
||||
import sys, json
|
||||
for s in json.loads(sys.stdin.read()):
|
||||
title = s.get('title','')
|
||||
if title.startswith('[CA-AUTO] worker-testinfra:'):
|
||||
area = title.replace('[CA-AUTO] worker-testinfra: ','')
|
||||
if title.startswith('[AUTO-INF] worker-testinfra:'):
|
||||
area = title.replace('[AUTO-INF] worker-testinfra: ','')
|
||||
print(area + '=' + s['id'])
|
||||
\"", timeout=30000)
|
||||
|
||||
@@ -195,7 +195,7 @@ LOOP:
|
||||
for area in batch:
|
||||
SESSION_ID = bash("curl -s -X POST ${SERVER}/session \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{\"title\": \"[CA-AUTO] worker-testinfra: <area>\"}' \
|
||||
-d '{\"title\": \"[AUTO-INF] worker-testinfra: <area>\"}' \
|
||||
| python3 -c \"import sys,json; print(json.loads(sys.stdin.read())['id'])\"",
|
||||
timeout=30000)
|
||||
bash("curl -s -X POST ${SERVER}/session/${SESSION_ID}/prompt_async \
|
||||
|
||||
@@ -125,8 +125,8 @@ EXISTING_WORKERS = bash("curl -s ${SERVER}/session | python3 -c \"
|
||||
import sys, json
|
||||
for s in json.loads(sys.stdin.read()):
|
||||
title = s.get('title','')
|
||||
if title.startswith('[CA-AUTO] worker-uat:'):
|
||||
area = title.replace('[CA-AUTO] worker-uat: ','')
|
||||
if title.startswith('[AUTO-UAT] worker-uat:'):
|
||||
area = title.replace('[AUTO-UAT] worker-uat: ','')
|
||||
print(area + '=' + s['id'])
|
||||
\"", timeout=30000)
|
||||
|
||||
@@ -162,7 +162,7 @@ LOOP:
|
||||
for area in batch:
|
||||
SESSION_ID = bash("curl -s -X POST ${SERVER}/session \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{\"title\": \"[CA-AUTO] worker-uat: <area>\"}' \
|
||||
-d '{\"title\": \"[AUTO-UAT] worker-uat: <area>\"}' \
|
||||
| python3 -c \"import sys,json; print(json.loads(sys.stdin.read())['id'])\"",
|
||||
timeout=30000)
|
||||
bash("curl -s -X POST ${SERVER}/session/${SESSION_ID}/prompt_async \
|
||||
|
||||
@@ -479,10 +479,10 @@ def adopt_existing_workers():
|
||||
continue
|
||||
|
||||
# Adopt issue implementation workers
|
||||
if title.startswith('[CA-AUTO] worker-issue-impl: issue-'):
|
||||
if title.startswith('[AUTO-IMP] worker-issue-impl: issue-'):
|
||||
try:
|
||||
# Extract issue number: "[CA-AUTO] worker-issue-impl: issue-123"
|
||||
issue_num_str = title.replace('[CA-AUTO] worker-issue-impl: issue-', '').strip()
|
||||
# Extract issue number: "[AUTO-IMP] worker-issue-impl: issue-123"
|
||||
issue_num_str = title.replace('[AUTO-IMP] worker-issue-impl: issue-', '').strip()
|
||||
issue_number = int(issue_num_str)
|
||||
active_issue_workers[issue_number] = session_id
|
||||
adopted_issue_workers += 1
|
||||
@@ -491,10 +491,10 @@ def adopt_existing_workers():
|
||||
print(f"[WARNING] Could not parse issue number from title: {title}")
|
||||
|
||||
# Adopt PR fix workers
|
||||
elif title.startswith('[CA-AUTO] worker-pr-fix: PR-'):
|
||||
elif title.startswith('[AUTO-IMP] worker-pr-fix: PR-'):
|
||||
try:
|
||||
# Extract PR number: "[CA-AUTO] worker-pr-fix: PR-456"
|
||||
pr_num_str = title.replace('[CA-AUTO] worker-pr-fix: PR-', '').strip()
|
||||
# Extract PR number: "[AUTO-IMP] worker-pr-fix: PR-456"
|
||||
pr_num_str = title.replace('[AUTO-IMP] worker-pr-fix: PR-', '').strip()
|
||||
pr_number = int(pr_num_str)
|
||||
|
||||
# We need to reconstruct the PR worker info - get PR data from Forgejo
|
||||
@@ -645,7 +645,7 @@ Your task: Fix this PR based on work_type:
|
||||
CRITICAL: You own this PR until it is merged. Monitor and handle all feedback.
|
||||
Do not exit until the PR is merged or blocked by human feedback (needs feedback label)."""
|
||||
|
||||
title = f"[CA-AUTO] worker-pr-fix: PR-{pr.number}"
|
||||
title = f"[AUTO-IMP] worker-pr-fix: PR-{pr.number}"
|
||||
work_id = f"PR-{pr.number}"
|
||||
|
||||
else: # issue-impl mode
|
||||
@@ -672,7 +672,7 @@ Your task: Implement this issue fully, create PR, and shepherd it through review
|
||||
CRITICAL: You own this issue from implementation through PR merge.
|
||||
Do not exit until the PR is merged. Monitor and handle all review feedback."""
|
||||
|
||||
title = f"[CA-AUTO] worker-issue-impl: issue-{issue['number']}"
|
||||
title = f"[AUTO-IMP] worker-issue-impl: issue-{issue['number']}"
|
||||
work_id = f"issue-{issue['number']}"
|
||||
|
||||
def verify_worker_started(session_id, retries=3):
|
||||
|
||||
@@ -517,13 +517,35 @@ ALL_SESSIONS = bash("curl -s ${SERVER}/session", timeout=30000)
|
||||
# Step 2: Find existing supervisor sessions
|
||||
EXISTING = bash("echo '${ALL_SESSIONS}' | python3 -c \"
|
||||
import sys, json
|
||||
import re
|
||||
sessions = json.loads(sys.stdin.read())
|
||||
# Map tags to display names
|
||||
tag_map = {
|
||||
'AUTO-IMP-SUP': 'implementor-pool',
|
||||
'AUTO-REV-SUP': 'reviewer-pool',
|
||||
'AUTO-UAT-SUP': 'tester-pool',
|
||||
'AUTO-BUG-SUP': 'hunter-pool',
|
||||
'AUTO-INF-SUP': 'test-infra-pool',
|
||||
'AUTO-ARCH': 'architect',
|
||||
'AUTO-EPIC': 'epic-planner',
|
||||
'AUTO-HUMAN': 'human-liaison',
|
||||
'AUTO-EVLV': 'agent-evolver',
|
||||
'AUTO-GUARD': 'arch-guard',
|
||||
'AUTO-SPEC': 'spec-updater',
|
||||
'AUTO-BLOG': 'backlog-groomer',
|
||||
'AUTO-DOCS': 'docs-writer',
|
||||
'AUTO-TIME': 'timeline-updater',
|
||||
'AUTO-OWNR': 'project-owner',
|
||||
'AUTO-WDOG': 'system-watchdog'
|
||||
}
|
||||
for s in sessions:
|
||||
title = s.get('title', '')
|
||||
if title.startswith('[CA-AUTO] supervisor:'):
|
||||
# Extract the display name from title
|
||||
name = title.replace('[CA-AUTO] supervisor: ', '')
|
||||
print(name + '=' + s['id'])
|
||||
# Check if title matches any supervisor tag pattern
|
||||
match = re.match(r'\\[([A-Z-]+)\\]', title)
|
||||
if match and match.group(1) in tag_map:
|
||||
tag = match.group(1)
|
||||
display_name = tag_map[tag]
|
||||
print(display_name + '=' + s['id'])
|
||||
\"", timeout=30000)
|
||||
|
||||
# Step 3: Check status of each existing session
|
||||
@@ -586,7 +608,7 @@ Pre-flight: Launching 16 supervisors via prompt_async:
|
||||
# ── Helper function: launch one supervisor ───────────────────────
|
||||
# For EACH supervisor, SKIP if already running (adopted in Phase C.0).
|
||||
|
||||
function launch_supervisor(agent_name, display_name, prompt_text):
|
||||
function launch_supervisor(agent_name, display_name, tag, prompt_text):
|
||||
# Check if this supervisor was adopted from a previous run
|
||||
if display_name in existing_supervisors:
|
||||
# Already running — record its session ID and skip launch
|
||||
@@ -596,7 +618,7 @@ function launch_supervisor(agent_name, display_name, prompt_text):
|
||||
# Step 1: Create a session
|
||||
SESSION_ID=$(curl -s -X POST "${SERVER}/session" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"title\": \"[CA-AUTO] supervisor: ${display_name}\"}" \
|
||||
-d "{\"title\": \"[${tag}] ${display_name}\"}" \
|
||||
| python3 -c "import sys,json; print(json.loads(sys.stdin.read())['id'])")
|
||||
|
||||
# Step 2: Fire-and-forget launch via prompt_async
|
||||
@@ -618,7 +640,7 @@ rm -f /tmp/ca-supervisor-sessions.env
|
||||
# Launch each with its specific prompt containing all needed parameters:
|
||||
# (Forgejo PAT, git identity, repo info, N, etc.)
|
||||
|
||||
launch_supervisor("issue-implementor", "implementor-pool",
|
||||
launch_supervisor("issue-implementor", "implementor-pool", "AUTO-IMP-SUP",
|
||||
"You are the implementation pool supervisor.
|
||||
SESSION STATE ISSUE: #{SESSION_STATE_ISSUE_NUMBER}
|
||||
Repo: <owner>/<repo>. Forgejo PAT: <PAT>.
|
||||
@@ -628,7 +650,7 @@ launch_supervisor("issue-implementor", "implementor-pool",
|
||||
When creating tracking issues, ALWAYS include these labels:
|
||||
Type/Automation, State/In Progress, Priority/Medium")
|
||||
|
||||
launch_supervisor("ca-continuous-pr-reviewer", "reviewer-pool",
|
||||
launch_supervisor("ca-continuous-pr-reviewer", "reviewer-pool", "AUTO-REV-SUP",
|
||||
"You are the PR review pool supervisor.
|
||||
SESSION STATE ISSUE: #{SESSION_STATE_ISSUE_NUMBER}
|
||||
Repo: <owner>/<repo>. Instance ID: reviewer-pool-1.
|
||||
@@ -637,7 +659,7 @@ launch_supervisor("ca-continuous-pr-reviewer", "reviewer-pool",
|
||||
When creating tracking issues, ALWAYS include these labels:
|
||||
Type/Automation, State/In Progress, Priority/Medium")
|
||||
|
||||
launch_supervisor("ca-uat-tester", "tester-pool",
|
||||
launch_supervisor("ca-uat-tester", "tester-pool", "AUTO-UAT-SUP",
|
||||
"You are the UAT testing pool supervisor.
|
||||
SESSION STATE ISSUE: #{SESSION_STATE_ISSUE_NUMBER}
|
||||
Repo: <owner>/<repo>. Instance ID: uat-pool-1.
|
||||
@@ -646,7 +668,7 @@ launch_supervisor("ca-uat-tester", "tester-pool",
|
||||
When creating tracking issues, ALWAYS include these labels:
|
||||
Type/Automation, State/In Progress, Priority/Medium")
|
||||
|
||||
launch_supervisor("ca-bug-hunter", "hunter-pool",
|
||||
launch_supervisor("ca-bug-hunter", "hunter-pool", "AUTO-BUG-SUP",
|
||||
"You are the bug hunting pool supervisor.
|
||||
SESSION STATE ISSUE: #{SESSION_STATE_ISSUE_NUMBER}
|
||||
Repo: <owner>/<repo>. Instance ID: hunter-pool-1.
|
||||
@@ -655,7 +677,7 @@ launch_supervisor("ca-bug-hunter", "hunter-pool",
|
||||
When creating tracking issues, ALWAYS include these labels:
|
||||
Type/Automation, State/In Progress, Priority/Medium")
|
||||
|
||||
launch_supervisor("ca-test-infra-improver", "test-infra-pool",
|
||||
launch_supervisor("ca-test-infra-improver", "test-infra-pool", "AUTO-INF-SUP",
|
||||
"You are the test infrastructure improvement pool supervisor.
|
||||
SESSION STATE ISSUE: #{SESSION_STATE_ISSUE_NUMBER}
|
||||
Repo: <owner>/<repo>. Instance ID: test-infra-pool-1.
|
||||
@@ -664,7 +686,7 @@ launch_supervisor("ca-test-infra-improver", "test-infra-pool",
|
||||
When creating tracking issues, ALWAYS include these labels:
|
||||
Type/Automation, State/In Progress, Priority/Medium")
|
||||
|
||||
launch_supervisor("ca-architect", "architect",
|
||||
launch_supervisor("ca-architect", "architect", "AUTO-ARCH",
|
||||
"You are the continuous architecture designer.
|
||||
SESSION STATE ISSUE: #{SESSION_STATE_ISSUE_NUMBER}
|
||||
Repo: <owner>/<repo>. Instance ID: architect-1.
|
||||
@@ -673,7 +695,7 @@ launch_supervisor("ca-architect", "architect",
|
||||
When creating tracking issues, ALWAYS include these labels:
|
||||
Type/Automation, State/In Progress, Priority/Medium")
|
||||
|
||||
launch_supervisor("ca-epic-planner", "epic-planner",
|
||||
launch_supervisor("ca-epic-planner", "epic-planner", "AUTO-EPIC",
|
||||
"You are the continuous epic planner.
|
||||
SESSION STATE ISSUE: #{SESSION_STATE_ISSUE_NUMBER}
|
||||
Repo: <owner>/<repo>. Instance ID: epic-planner-1.
|
||||
@@ -681,7 +703,7 @@ launch_supervisor("ca-epic-planner", "epic-planner",
|
||||
When creating tracking issues, ALWAYS include these labels:
|
||||
Type/Automation, State/In Progress, Priority/Medium")
|
||||
|
||||
launch_supervisor("ca-human-liaison", "human-liaison",
|
||||
launch_supervisor("ca-human-liaison", "human-liaison", "AUTO-HUMAN",
|
||||
"You are the human liaison.
|
||||
SESSION STATE ISSUE: #{SESSION_STATE_ISSUE_NUMBER}
|
||||
Repo: <owner>/<repo>. Instance ID: human-liaison-1.
|
||||
@@ -689,7 +711,7 @@ launch_supervisor("ca-human-liaison", "human-liaison",
|
||||
When creating tracking issues, ALWAYS include these labels:
|
||||
Type/Automation, State/In Progress, Priority/Medium")
|
||||
|
||||
launch_supervisor("ca-agent-evolver", "agent-evolver",
|
||||
launch_supervisor("ca-agent-evolver", "agent-evolver", "AUTO-EVLV",
|
||||
"You are the agent evolver.
|
||||
SESSION STATE ISSUE: #{SESSION_STATE_ISSUE_NUMBER}
|
||||
Repo: <owner>/<repo>. Instance ID: agent-evolver-1.
|
||||
@@ -697,7 +719,7 @@ launch_supervisor("ca-agent-evolver", "agent-evolver",
|
||||
When creating tracking issues, ALWAYS include these labels:
|
||||
Type/Automation, State/In Progress, Priority/Medium")
|
||||
|
||||
launch_supervisor("ca-architecture-guard", "arch-guard",
|
||||
launch_supervisor("ca-architecture-guard", "arch-guard", "AUTO-GUARD",
|
||||
"You are the architecture guard.
|
||||
SESSION STATE ISSUE: #{SESSION_STATE_ISSUE_NUMBER}
|
||||
Repo: <owner>/<repo>. Forgejo PAT: <PAT>.
|
||||
@@ -705,7 +727,7 @@ launch_supervisor("ca-architecture-guard", "arch-guard",
|
||||
When creating tracking issues, ALWAYS include these labels:
|
||||
Type/Automation, State/In Progress, Priority/Medium")
|
||||
|
||||
launch_supervisor("ca-spec-updater", "spec-updater",
|
||||
launch_supervisor("ca-spec-updater", "spec-updater", "AUTO-SPEC",
|
||||
"You are the spec updater.
|
||||
SESSION STATE ISSUE: #{SESSION_STATE_ISSUE_NUMBER}
|
||||
Repo: <owner>/<repo>. Forgejo PAT: <PAT>.
|
||||
@@ -713,7 +735,7 @@ launch_supervisor("ca-spec-updater", "spec-updater",
|
||||
When creating tracking issues, ALWAYS include these labels:
|
||||
Type/Automation, State/In Progress, Priority/Medium")
|
||||
|
||||
launch_supervisor("ca-backlog-groomer", "backlog-groomer",
|
||||
launch_supervisor("ca-backlog-groomer", "backlog-groomer", "AUTO-BLOG",
|
||||
"You are the backlog groomer.
|
||||
SESSION STATE ISSUE: #{SESSION_STATE_ISSUE_NUMBER}
|
||||
Repo: <owner>/<repo>. Instance ID: groomer-1.
|
||||
@@ -721,7 +743,7 @@ launch_supervisor("ca-backlog-groomer", "backlog-groomer",
|
||||
When creating tracking issues, ALWAYS include these labels:
|
||||
Type/Automation, State/In Progress, Priority/Medium")
|
||||
|
||||
launch_supervisor("ca-docs-writer", "docs-writer",
|
||||
launch_supervisor("ca-docs-writer", "docs-writer", "AUTO-DOCS",
|
||||
"You are the documentation writer.
|
||||
SESSION STATE ISSUE: #{SESSION_STATE_ISSUE_NUMBER}
|
||||
Repo: <owner>/<repo>. Forgejo PAT: <PAT>.
|
||||
@@ -729,7 +751,7 @@ launch_supervisor("ca-docs-writer", "docs-writer",
|
||||
When creating tracking issues, ALWAYS include these labels:
|
||||
Type/Automation, State/In Progress, Priority/Medium")
|
||||
|
||||
launch_supervisor("ca-timeline-updater", "timeline-updater",
|
||||
launch_supervisor("ca-timeline-updater", "timeline-updater", "AUTO-TIME",
|
||||
"You are the timeline updater.
|
||||
SESSION STATE ISSUE: #{SESSION_STATE_ISSUE_NUMBER}
|
||||
Repo: <owner>/<repo>. Forgejo PAT: <PAT>.
|
||||
@@ -737,7 +759,7 @@ launch_supervisor("ca-timeline-updater", "timeline-updater",
|
||||
When creating tracking issues, ALWAYS include these labels:
|
||||
Type/Automation, State/In Progress, Priority/Medium")
|
||||
|
||||
launch_supervisor("ca-project-owner", "project-owner",
|
||||
launch_supervisor("ca-project-owner", "project-owner", "AUTO-OWNR",
|
||||
"You are the project owner and triager.
|
||||
SESSION STATE ISSUE: #{SESSION_STATE_ISSUE_NUMBER}
|
||||
Repo: <owner>/<repo>. Instance ID: project-owner-1.
|
||||
@@ -745,7 +767,7 @@ launch_supervisor("ca-project-owner", "project-owner",
|
||||
When creating tracking issues, ALWAYS include these labels:
|
||||
Type/Automation, State/In Progress, Priority/Medium")
|
||||
|
||||
launch_supervisor("ca-system-watchdog", "system-watchdog",
|
||||
launch_supervisor("ca-system-watchdog", "system-watchdog", "AUTO-WDOG",
|
||||
"You are the system watchdog.
|
||||
SESSION STATE ISSUE: #{SESSION_STATE_ISSUE_NUMBER}
|
||||
Repo: <owner>/<repo>. Instance ID: watchdog-1.
|
||||
@@ -810,6 +832,91 @@ invoke ca-session-persister with:
|
||||
supervisors_relaunched = 0
|
||||
heartbeat_count = 0
|
||||
|
||||
# ── Supervisor metadata mapping for re-launching ─────────────────
|
||||
# Maps display_name -> {agent_name, tag, prompt_template}
|
||||
SUPERVISOR_METADATA = {
|
||||
"implementor-pool": {
|
||||
"agent": "issue-implementor",
|
||||
"tag": "AUTO-IMP-SUP",
|
||||
"prompt": "You are the implementation pool supervisor..."
|
||||
},
|
||||
"reviewer-pool": {
|
||||
"agent": "ca-continuous-pr-reviewer",
|
||||
"tag": "AUTO-REV-SUP",
|
||||
"prompt": "You are the PR review pool supervisor..."
|
||||
},
|
||||
"tester-pool": {
|
||||
"agent": "ca-uat-tester",
|
||||
"tag": "AUTO-UAT-SUP",
|
||||
"prompt": "You are the UAT testing pool supervisor..."
|
||||
},
|
||||
"hunter-pool": {
|
||||
"agent": "ca-bug-hunter",
|
||||
"tag": "AUTO-BUG-SUP",
|
||||
"prompt": "You are the bug hunting pool supervisor..."
|
||||
},
|
||||
"test-infra-pool": {
|
||||
"agent": "ca-test-infra-improver",
|
||||
"tag": "AUTO-INF-SUP",
|
||||
"prompt": "You are the test infrastructure improvement pool supervisor..."
|
||||
},
|
||||
"architect": {
|
||||
"agent": "ca-architect",
|
||||
"tag": "AUTO-ARCH",
|
||||
"prompt": "You are the continuous architecture designer..."
|
||||
},
|
||||
"epic-planner": {
|
||||
"agent": "ca-epic-planner",
|
||||
"tag": "AUTO-EPIC",
|
||||
"prompt": "You are the continuous epic planner..."
|
||||
},
|
||||
"human-liaison": {
|
||||
"agent": "ca-human-liaison",
|
||||
"tag": "AUTO-HUMAN",
|
||||
"prompt": "You are the human liaison..."
|
||||
},
|
||||
"agent-evolver": {
|
||||
"agent": "ca-agent-evolver",
|
||||
"tag": "AUTO-EVLV",
|
||||
"prompt": "You are the agent evolver..."
|
||||
},
|
||||
"arch-guard": {
|
||||
"agent": "ca-architecture-guard",
|
||||
"tag": "AUTO-GUARD",
|
||||
"prompt": "You are the architecture guard..."
|
||||
},
|
||||
"spec-updater": {
|
||||
"agent": "ca-spec-updater",
|
||||
"tag": "AUTO-SPEC",
|
||||
"prompt": "You are the spec updater..."
|
||||
},
|
||||
"backlog-groomer": {
|
||||
"agent": "ca-backlog-groomer",
|
||||
"tag": "AUTO-BLOG",
|
||||
"prompt": "You are the backlog groomer..."
|
||||
},
|
||||
"docs-writer": {
|
||||
"agent": "ca-docs-writer",
|
||||
"tag": "AUTO-DOCS",
|
||||
"prompt": "You are the documentation writer..."
|
||||
},
|
||||
"timeline-updater": {
|
||||
"agent": "ca-timeline-updater",
|
||||
"tag": "AUTO-TIME",
|
||||
"prompt": "You are the timeline updater..."
|
||||
},
|
||||
"project-owner": {
|
||||
"agent": "ca-project-owner",
|
||||
"tag": "AUTO-OWNR",
|
||||
"prompt": "You are the project owner and triager..."
|
||||
},
|
||||
"system-watchdog": {
|
||||
"agent": "ca-system-watchdog",
|
||||
"tag": "AUTO-WDOG",
|
||||
"prompt": "You are the system watchdog..."
|
||||
}
|
||||
}
|
||||
|
||||
MONITORING LOOP (runs until product is verified complete):
|
||||
|
||||
# ── Sleep 60 seconds ─────────────────────────────────────────
|
||||
@@ -823,6 +930,33 @@ MONITORING LOOP (runs until product is verified complete):
|
||||
# ── Check session status for all supervisors ─────────────────
|
||||
# Use Bash tool to curl the session status endpoint:
|
||||
STATUS = bash("curl -s ${SERVER}/session/status")
|
||||
|
||||
# ── Count supervisors and workers by tag ─────────────────────
|
||||
# Get all sessions and count by tag pattern
|
||||
ALL_SESSIONS = bash("curl -s ${SERVER}/session")
|
||||
|
||||
# Count pool supervisors (should be exactly 1 each)
|
||||
IMP_SUP_COUNT = bash("echo '${ALL_SESSIONS}' | grep -c '\\[AUTO-IMP-SUP\\]' || echo 0")
|
||||
REV_SUP_COUNT = bash("echo '${ALL_SESSIONS}' | grep -c '\\[AUTO-REV-SUP\\]' || echo 0")
|
||||
UAT_SUP_COUNT = bash("echo '${ALL_SESSIONS}' | grep -c '\\[AUTO-UAT-SUP\\]' || echo 0")
|
||||
BUG_SUP_COUNT = bash("echo '${ALL_SESSIONS}' | grep -c '\\[AUTO-BUG-SUP\\]' || echo 0")
|
||||
INF_SUP_COUNT = bash("echo '${ALL_SESSIONS}' | grep -c '\\[AUTO-INF-SUP\\]' || echo 0")
|
||||
|
||||
# Count workers by type
|
||||
IMP_WORK_COUNT = bash("echo '${ALL_SESSIONS}' | grep -c '\\[AUTO-IMP\\]' || echo 0")
|
||||
REV_WORK_COUNT = bash("echo '${ALL_SESSIONS}' | grep -c '\\[AUTO-REV\\]' || echo 0")
|
||||
UAT_WORK_COUNT = bash("echo '${ALL_SESSIONS}' | grep -c '\\[AUTO-UAT\\]' || echo 0")
|
||||
BUG_WORK_COUNT = bash("echo '${ALL_SESSIONS}' | grep -c '\\[AUTO-BUG\\]' || echo 0")
|
||||
INF_WORK_COUNT = bash("echo '${ALL_SESSIONS}' | grep -c '\\[AUTO-INF\\]' || echo 0")
|
||||
|
||||
# Count singleton supervisors
|
||||
SINGLETON_COUNTS = bash("echo '${ALL_SESSIONS}' | grep -E '\\[AUTO-(ARCH|EPIC|HUMAN|EVLV|GUARD|SPEC|BLOG|DOCS|TIME|OWNR|WDOG)\\]' | wc -l || echo 0")
|
||||
|
||||
# Log counts every 10 heartbeats
|
||||
if heartbeat_count % 10 == 0:
|
||||
echo "Supervisor counts: IMP=${IMP_SUP_COUNT}, REV=${REV_SUP_COUNT}, UAT=${UAT_SUP_COUNT}, BUG=${BUG_SUP_COUNT}, INF=${INF_SUP_COUNT}"
|
||||
echo "Worker counts: IMP=${IMP_WORK_COUNT}, REV=${REV_WORK_COUNT}, UAT=${UAT_WORK_COUNT}, BUG=${BUG_WORK_COUNT}, INF=${INF_WORK_COUNT}"
|
||||
echo "Singleton supervisors: ${SINGLETON_COUNTS}/11"
|
||||
|
||||
# Parse status to find sessions that are no longer active
|
||||
for each supervisor in /tmp/ca-supervisor-sessions.env:
|
||||
@@ -831,8 +965,10 @@ MONITORING LOOP (runs until product is verified complete):
|
||||
|
||||
if session is completed or errored or not found:
|
||||
# ── IMMEDIATELY re-launch this supervisor ────────────
|
||||
# Get metadata for this supervisor
|
||||
metadata = SUPERVISOR_METADATA[display_name]
|
||||
# Create new session + prompt_async (same as Phase C.2)
|
||||
launch_supervisor(agent_name, display_name, prompt_text)
|
||||
launch_supervisor(metadata["agent"], display_name, metadata["tag"], metadata["prompt"])
|
||||
supervisors_relaunched += 1
|
||||
# Update the tracking file with the new session ID
|
||||
|
||||
@@ -863,7 +999,8 @@ MONITORING LOOP (runs until product is verified complete):
|
||||
"Supervisor: Product Builder | Agent: product-builder"
|
||||
)
|
||||
# Re-launch the zombie supervisor
|
||||
launch_supervisor(agent_name, display_name, prompt_text)
|
||||
metadata = SUPERVISOR_METADATA[display_name]
|
||||
launch_supervisor(metadata["agent"], display_name, metadata["tag"], metadata["prompt"])
|
||||
supervisors_relaunched += 1
|
||||
|
||||
# ── Check system watchdog alerts (every 3 heartbeats) ────────
|
||||
|
||||
Reference in New Issue
Block a user