Files
bzzz/pkg/coordination/dependency_detector.go
anthonyrawlins 065dddf8d5 Prepare for v2 development: Add MCP integration and future development planning
- Add FUTURE_DEVELOPMENT.md with comprehensive v2 protocol specification
- Add MCP integration design and implementation foundation
- Add infrastructure and deployment configurations
- Update system architecture for v2 evolution

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-07 14:38:22 +10:00

254 lines
8.8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package coordination
import (
"context"
"fmt"
"strings"
"time"
"github.com/anthonyrawlins/bzzz/pubsub"
"github.com/libp2p/go-libp2p/core/peer"
)
// DependencyDetector analyzes tasks across repositories for relationships
type DependencyDetector struct {
pubsub *pubsub.PubSub
ctx context.Context
knownTasks map[string]*TaskContext // taskKey -> context
dependencyRules []DependencyRule
coordinationHops int
}
// TaskContext represents a task with its repository and project context
type TaskContext struct {
TaskID int `json:"task_id"`
ProjectID int `json:"project_id"`
Repository string `json:"repository"`
Title string `json:"title"`
Description string `json:"description"`
Keywords []string `json:"keywords"`
AgentID string `json:"agent_id"`
ClaimedAt time.Time `json:"claimed_at"`
}
// DependencyRule defines how to detect task relationships
type DependencyRule struct {
Name string
Description string
Keywords []string
Validator func(task1, task2 *TaskContext) (bool, string)
}
// TaskDependency represents a detected relationship between tasks
type TaskDependency struct {
Task1 *TaskContext `json:"task1"`
Task2 *TaskContext `json:"task2"`
Relationship string `json:"relationship"`
Confidence float64 `json:"confidence"`
Reason string `json:"reason"`
DetectedAt time.Time `json:"detected_at"`
}
// NewDependencyDetector creates a new cross-repository dependency detector
func NewDependencyDetector(ctx context.Context, ps *pubsub.PubSub) *DependencyDetector {
dd := &DependencyDetector{
pubsub: ps,
ctx: ctx,
knownTasks: make(map[string]*TaskContext),
coordinationHops: 3, // Limit meta discussion depth
}
// Initialize common dependency detection rules
dd.initializeDependencyRules()
// Subscribe to task announcements for dependency detection
go dd.listenForTaskAnnouncements()
return dd
}
// initializeDependencyRules sets up common patterns for task relationships
func (dd *DependencyDetector) initializeDependencyRules() {
dd.dependencyRules = []DependencyRule{
{
Name: "API_Contract",
Description: "Tasks involving API contracts and implementations",
Keywords: []string{"api", "endpoint", "contract", "interface", "schema"},
Validator: func(task1, task2 *TaskContext) (bool, string) {
// Check if one task defines API and another implements it
text1 := strings.ToLower(task1.Title + " " + task1.Description)
text2 := strings.ToLower(task2.Title + " " + task2.Description)
if (strings.Contains(text1, "api") && strings.Contains(text2, "implement")) ||
(strings.Contains(text2, "api") && strings.Contains(text1, "implement")) {
return true, "API definition and implementation dependency"
}
return false, ""
},
},
{
Name: "Database_Schema",
Description: "Database schema changes affecting multiple services",
Keywords: []string{"database", "schema", "migration", "table", "model"},
Validator: func(task1, task2 *TaskContext) (bool, string) {
text1 := strings.ToLower(task1.Title + " " + task1.Description)
text2 := strings.ToLower(task2.Title + " " + task2.Description)
dbKeywords := []string{"database", "schema", "migration", "table"}
hasDB1 := false
hasDB2 := false
for _, keyword := range dbKeywords {
if strings.Contains(text1, keyword) { hasDB1 = true }
if strings.Contains(text2, keyword) { hasDB2 = true }
}
if hasDB1 && hasDB2 {
return true, "Database schema dependency detected"
}
return false, ""
},
},
{
Name: "Configuration_Dependency",
Description: "Configuration changes affecting multiple components",
Keywords: []string{"config", "environment", "settings", "parameters"},
Validator: func(task1, task2 *TaskContext) (bool, string) {
text1 := strings.ToLower(task1.Title + " " + task1.Description)
text2 := strings.ToLower(task2.Title + " " + task2.Description)
if (strings.Contains(text1, "config") || strings.Contains(text1, "environment")) &&
(strings.Contains(text2, "config") || strings.Contains(text2, "environment")) {
return true, "Configuration dependency - coordinated changes needed"
}
return false, ""
},
},
{
Name: "Security_Compliance",
Description: "Security changes requiring coordinated implementation",
Keywords: []string{"security", "auth", "permission", "token", "encrypt"},
Validator: func(task1, task2 *TaskContext) (bool, string) {
text1 := strings.ToLower(task1.Title + " " + task1.Description)
text2 := strings.ToLower(task2.Title + " " + task2.Description)
secKeywords := []string{"security", "auth", "permission", "token"}
hasSecu1 := false
hasSecu2 := false
for _, keyword := range secKeywords {
if strings.Contains(text1, keyword) { hasSecu1 = true }
if strings.Contains(text2, keyword) { hasSecu2 = true }
}
if hasSecu1 && hasSecu2 {
return true, "Security implementation requires coordination"
}
return false, ""
},
},
}
}
// RegisterTask adds a task to the dependency tracking system
func (dd *DependencyDetector) RegisterTask(task *TaskContext) {
taskKey := fmt.Sprintf("%d:%d", task.ProjectID, task.TaskID)
dd.knownTasks[taskKey] = task
fmt.Printf("🔍 Registered task for dependency detection: %s/%s #%d\n",
task.Repository, task.Title, task.TaskID)
// Check for dependencies with existing tasks
dd.detectDependencies(task)
}
// detectDependencies analyzes a new task against existing tasks for relationships
func (dd *DependencyDetector) detectDependencies(newTask *TaskContext) {
for _, existingTask := range dd.knownTasks {
// Skip self-comparison
if existingTask.TaskID == newTask.TaskID && existingTask.ProjectID == newTask.ProjectID {
continue
}
// Skip if same repository (handled by single-repo coordination)
if existingTask.Repository == newTask.Repository {
continue
}
// Apply dependency detection rules
for _, rule := range dd.dependencyRules {
if matches, reason := rule.Validator(newTask, existingTask); matches {
dependency := &TaskDependency{
Task1: newTask,
Task2: existingTask,
Relationship: rule.Name,
Confidence: 0.8, // Could be improved with ML
Reason: reason,
DetectedAt: time.Now(),
}
dd.announceDependency(dependency)
}
}
}
}
// announceDependency broadcasts a detected dependency for agent coordination
func (dd *DependencyDetector) announceDependency(dep *TaskDependency) {
fmt.Printf("🔗 Dependency detected: %s/%s #%d ↔ %s/%s #%d (%s)\n",
dep.Task1.Repository, dep.Task1.Title, dep.Task1.TaskID,
dep.Task2.Repository, dep.Task2.Title, dep.Task2.TaskID,
dep.Relationship)
// Create coordination message for HMMM meta-discussion
coordMsg := map[string]interface{}{
"message_type": "dependency_detected",
"dependency": dep,
"coordination_request": fmt.Sprintf(
"Cross-repository dependency detected between tasks. "+
"Agent working on %s/%s #%d and agent working on %s/%s #%d should coordinate. "+
"Relationship: %s. Reason: %s",
dep.Task1.Repository, dep.Task1.Title, dep.Task1.TaskID,
dep.Task2.Repository, dep.Task2.Title, dep.Task2.TaskID,
dep.Relationship, dep.Reason,
),
"agents_involved": []string{dep.Task1.AgentID, dep.Task2.AgentID},
"repositories": []string{dep.Task1.Repository, dep.Task2.Repository},
"hop_count": 0,
"max_hops": dd.coordinationHops,
"detected_at": dep.DetectedAt.Unix(),
}
// Publish to HMMM meta-discussion channel
if err := dd.pubsub.PublishHmmmMessage(pubsub.MetaDiscussion, coordMsg); err != nil {
fmt.Printf("❌ Failed to announce dependency: %v\n", err)
} else {
fmt.Printf("📡 Dependency coordination request sent to HMMM channel\n")
}
}
// listenForTaskAnnouncements monitors the P2P mesh for task claims
func (dd *DependencyDetector) listenForTaskAnnouncements() {
// This would integrate with the existing pubsub system
// to automatically detect when agents claim tasks
fmt.Printf("👂 Dependency detector listening for task announcements...\n")
// In a real implementation, this would subscribe to TaskClaim messages
// and extract task context for dependency analysis
}
// GetKnownTasks returns all tasks currently being tracked
func (dd *DependencyDetector) GetKnownTasks() map[string]*TaskContext {
return dd.knownTasks
}
// GetDependencyRules returns the configured dependency detection rules
func (dd *DependencyDetector) GetDependencyRules() []DependencyRule {
return dd.dependencyRules
}
// AddCustomRule allows adding project-specific dependency detection
func (dd *DependencyDetector) AddCustomRule(rule DependencyRule) {
dd.dependencyRules = append(dd.dependencyRules, rule)
fmt.Printf(" Added custom dependency rule: %s\n", rule.Name)
}