Refactor cockpit to use DockerTmuxController pattern

Based on claude-code-tools TmuxCLIController, this refactor:

- Added DockerTmuxController class for robust tmux session management
- Implements send_keys() with configurable delay_enter
- Implements capture_pane() for output retrieval
- Implements wait_for_prompt() for pattern-based completion detection
- Implements wait_for_idle() for content-hash-based idle detection
- Implements wait_for_shell_prompt() for shell prompt detection

Also includes workflow improvements:
- Pre-task git snapshot before agent execution
- Post-task commit protocol in agent guidelines

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
admin
2026-01-14 10:42:16 -03:00
commit ec33ac1936
265 changed files with 92011 additions and 0 deletions

View File

@@ -0,0 +1,323 @@
#!/usr/bin/env python3
"""
Sub-Agent Flow Integration - Integrates sub-agent context with Luzia 9-phase flow
Features:
1. Inject parent context into sub-agent flow execution
2. Execute 9-phase flow with context awareness
3. Coordinate sub-agent execution
4. Aggregate results from sub-agents
5. Propagate learnings back to parent task
"""
from typing import Dict, List, Optional, Any, Callable
from datetime import datetime
from sub_agent_context import SubAgentContextManager, SubAgentContext
class SubAgentFlowIntegrator:
"""Integrates sub-agent context management with task execution flow"""
def __init__(self, context_manager: Optional[SubAgentContextManager] = None):
"""Initialize flow integrator
Args:
context_manager: SubAgentContextManager instance
"""
self.context_manager = context_manager or SubAgentContextManager()
self.phase_handlers: Dict[str, Callable] = {}
def register_phase_handler(
self, phase_name: str, handler: Callable[[SubAgentContext], Dict[str, Any]]
) -> None:
"""Register handler for a specific phase
Args:
phase_name: Name of phase (e.g., 'CONTEXT_PREP', 'ANALYZING')
handler: Callable that executes phase logic
"""
self.phase_handlers[phase_name] = handler
def execute_sub_agent_flow(
self,
parent_task_id: str,
parent_project: str,
parent_description: str,
parent_context: Optional[Dict[str, Any]] = None,
parent_tags: Optional[List[str]] = None,
parent_metadata: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
"""Execute full 9-phase flow for a sub-agent
Args:
parent_task_id: ID of parent task
parent_project: Parent project
parent_description: Parent task description
parent_context: Parent task context
parent_tags: Tags from parent
parent_metadata: Metadata from parent
Returns:
Results from all phases
"""
# Create sub-agent context
context = self.context_manager.create_sub_agent_context(
parent_task_id=parent_task_id,
parent_project=parent_project,
parent_description=parent_description,
parent_context=parent_context,
parent_tags=parent_tags,
parent_metadata=parent_metadata,
)
results = {"sub_agent_id": context.sub_agent_id, "phases": {}}
# Execute each phase
phases = [p.phase_name for p in context.phase_progression]
for phase_name in phases:
phase_result = self.execute_phase(context.sub_agent_id, phase_name)
results["phases"][phase_name] = phase_result
return results
def execute_phase(self, sub_agent_id: str, phase_name: str) -> Dict[str, Any]:
"""Execute a single phase for a sub-agent
Args:
sub_agent_id: ID of sub-agent
phase_name: Name of phase to execute
Returns:
Phase execution results
"""
context = self.context_manager.get_sub_agent_context(sub_agent_id)
if not context:
return {"error": f"Context not found for {sub_agent_id}"}
# Mark phase as in progress
self.context_manager.update_phase(sub_agent_id, phase_name, "in_progress")
try:
# Execute phase handler if registered
if phase_name in self.phase_handlers:
handler = self.phase_handlers[phase_name]
output = handler(context)
else:
# Default phase execution
output = self._execute_default_phase(context, phase_name)
# Mark phase as complete
self.context_manager.update_phase(
sub_agent_id, phase_name, "completed", output=str(output)
)
return {"status": "completed", "output": output}
except Exception as e:
# Mark phase as failed
self.context_manager.update_phase(
sub_agent_id, phase_name, "failed", error=str(e)
)
return {"status": "failed", "error": str(e)}
def _execute_default_phase(self, context: SubAgentContext, phase_name: str) -> Dict[str, Any]:
"""Execute default behavior for a phase
Args:
context: SubAgentContext
phase_name: Name of phase
Returns:
Phase output
"""
output = {
"phase": phase_name,
"parent_task": context.parent_task_id,
"parent_project": context.parent_project,
"sibling_agents": len(context.sibling_agents),
}
if phase_name == "CONTEXT_PREP":
output["action"] = "Preparing context from parent task"
output["parent_description"] = context.parent_description
output["context_keys"] = list(context.parent_context.keys())
elif phase_name == "RECEIVED":
output["action"] = "Received and registered sub-agent"
output["sub_agent_id"] = context.sub_agent_id
output["created_at"] = context.created_at
elif phase_name == "PREDICTING":
output["action"] = "Predicting sub-agent requirements"
output["parent_tags"] = context.parent_tags
output["metadata_available"] = bool(context.parent_metadata)
elif phase_name == "ANALYZING":
output["action"] = "Analyzing parent task context"
output["parent_tags_count"] = len(context.parent_tags)
output["coordination_needed"] = len(context.sibling_agents) > 0
elif phase_name == "CONSENSUS_CHECK":
output["action"] = "Checking consensus with siblings"
output["sibling_agents"] = list(context.sibling_agents)
output["messages_sent"] = len(context.coordination_messages)
elif phase_name == "AWAITING_APPROVAL":
output["action"] = "Awaiting approval to proceed"
output["ready_to_execute"] = True
elif phase_name == "STRATEGIZING":
output["action"] = "Strategizing execution approach"
output["strategy"] = f"Execute sub-task within parent context"
elif phase_name == "EXECUTING":
output["action"] = "Executing sub-agent task"
output["execution_start"] = datetime.utcnow().isoformat()
elif phase_name == "LEARNING":
output["action"] = "Learning from execution"
output["parent_project"] = context.parent_project
output["completion_status"] = "ready"
return output
def get_sub_agent_progress(self, sub_agent_id: str) -> Dict[str, Any]:
"""Get progress report for a sub-agent
Args:
sub_agent_id: ID of sub-agent
Returns:
Progress information
"""
context = self.context_manager.get_sub_agent_context(sub_agent_id)
if not context:
return {"error": f"Context not found for {sub_agent_id}"}
phases = context.phase_progression
completed_phases = [p for p in phases if p.status == "completed"]
in_progress_phases = [p for p in phases if p.status == "in_progress"]
failed_phases = [p for p in phases if p.status == "failed"]
current_phase = self.context_manager.get_current_phase(sub_agent_id)
total_duration = sum(p.duration_seconds or 0 for p in completed_phases)
return {
"sub_agent_id": sub_agent_id,
"total_phases": len(phases),
"completed_phases": len(completed_phases),
"in_progress_phases": len(in_progress_phases),
"failed_phases": len(failed_phases),
"current_phase": current_phase,
"progress_percentage": (len(completed_phases) / len(phases)) * 100 if phases else 0,
"total_duration_seconds": total_duration,
"phase_details": [
{
"name": p.phase_name,
"status": p.status,
"duration": p.duration_seconds,
}
for p in phases
],
}
def coordinate_sub_agents(
self,
parent_task_id: str,
coordination_strategy: str = "sequential",
) -> Dict[str, Any]:
"""Coordinate execution of multiple sub-agents for a parent task
Args:
parent_task_id: ID of parent task
coordination_strategy: 'sequential', 'parallel', or 'dependency-based'
Returns:
Coordination results
"""
sub_agent_ids = self.context_manager.get_sub_agents_for_parent(parent_task_id)
if not sub_agent_ids:
return {"status": "no_sub_agents", "parent_task_id": parent_task_id}
results = {
"parent_task_id": parent_task_id,
"strategy": coordination_strategy,
"sub_agents": sub_agent_ids,
"coordination_details": [],
}
if coordination_strategy == "sequential":
# Execute sub-agents sequentially
for i, sub_agent_id in enumerate(sub_agent_ids):
context = self.context_manager.get_sub_agent_context(sub_agent_id)
results["coordination_details"].append(
{
"order": i + 1,
"sub_agent_id": sub_agent_id,
"siblings_count": len(context.sibling_agents) if context else 0,
"strategy": "Execute after previous sub-agent completes",
}
)
elif coordination_strategy == "parallel":
# Mark all sub-agents for parallel execution
for sub_agent_id in sub_agent_ids:
results["coordination_details"].append(
{
"sub_agent_id": sub_agent_id,
"strategy": "Execute simultaneously with other sub-agents",
}
)
elif coordination_strategy == "dependency-based":
# Analyze sibling relationships for dependency-based execution
for sub_agent_id in sub_agent_ids:
siblings = self.context_manager.get_sibling_agents(sub_agent_id)
results["coordination_details"].append(
{
"sub_agent_id": sub_agent_id,
"depends_on": list(siblings),
"strategy": "Execute considering dependencies on siblings",
}
)
return results
def collect_sub_agent_results(
self, parent_task_id: str
) -> Dict[str, Any]:
"""Collect and aggregate results from all sub-agents
Args:
parent_task_id: ID of parent task
Returns:
Aggregated results
"""
sub_agent_ids = self.context_manager.get_sub_agents_for_parent(parent_task_id)
results = {
"parent_task_id": parent_task_id,
"sub_agents_total": len(sub_agent_ids),
"sub_agents": [],
}
for sub_agent_id in sub_agent_ids:
progress = self.get_sub_agent_progress(sub_agent_id)
summary = self.context_manager.get_context_summary(sub_agent_id)
results["sub_agents"].append(
{
"sub_agent_id": sub_agent_id,
"progress": progress,
"summary": summary,
}
)
# Aggregate status
all_completed = all(
p.get("completed_phases") == p.get("total_phases")
for p in [s["progress"] for s in results["sub_agents"]]
)
results["all_sub_agents_complete"] = all_completed
return results