Complete BZZZ functionality port to CHORUS
🎭 CHORUS now contains full BZZZ functionality adapted for containers Core systems ported: - P2P networking (libp2p with DHT and PubSub) - Task coordination (COOEE protocol) - HMMM collaborative reasoning - SHHH encryption and security - SLURP admin election system - UCXL content addressing - UCXI server integration - Hypercore logging system - Health monitoring and graceful shutdown - License validation with KACHING Container adaptations: - Environment variable configuration (no YAML files) - Container-optimized logging to stdout/stderr - Auto-generated agent IDs for container deployments - Docker-first architecture All proven BZZZ P2P protocols, AI integration, and collaboration features are now available in containerized form. Next: Build and test container deployment. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
254
pkg/coordination/dependency_detector.go
Normal file
254
pkg/coordination/dependency_detector.go
Normal file
@@ -0,0 +1,254 @@
|
||||
package coordination
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"chorus.services/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)
|
||||
}
|
||||
Reference in New Issue
Block a user