package hapui
import (
"bufio"
"context"
"crypto/rand"
"encoding/json"
"fmt"
"html/template"
"math/big"
"net/http"
"os"
"strconv"
"strings"
"time"
"chorus/internal/runtime"
"chorus/pkg/hmmm"
"chorus/pkg/ucxl"
"chorus/pkg/storage"
"chorus/pubsub"
)
// TerminalInterface provides an interactive terminal interface for human agents
type TerminalInterface struct {
runtime *runtime.SharedRuntime
scanner *bufio.Scanner
quit chan bool
collaborativeSession *CollaborativeSession
hmmmMessageCount int
webServer *http.Server
}
// CollaborativeSession represents an active collaborative editing session
type CollaborativeSession struct {
SessionID string
Owner string
Participants []string
Status string
CreatedAt time.Time
}
// Decision represents a network decision awaiting votes
type Decision struct {
ID string `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
Type string `json:"type"`
Proposer string `json:"proposer"`
ProposerType string `json:"proposer_type"`
CreatedAt time.Time `json:"created_at"`
Deadline time.Time `json:"deadline"`
Status string `json:"status"`
Votes map[string]DecisionVote `json:"votes"`
Metadata map[string]interface{} `json:"metadata"`
Version int `json:"version"`
}
// DecisionVote represents a single vote on a decision
type DecisionVote struct {
VoterID string `json:"voter_id"`
VoterType string `json:"voter_type"`
Vote string `json:"vote"` // approve, reject, defer, abstain
Reasoning string `json:"reasoning"`
Timestamp time.Time `json:"timestamp"`
Confidence float64 `json:"confidence"` // 0.0-1.0 confidence in vote
}
// NewTerminalInterface creates a new terminal interface for HAP
func NewTerminalInterface(runtime *runtime.SharedRuntime) *TerminalInterface {
return &TerminalInterface{
runtime: runtime,
scanner: bufio.NewScanner(os.Stdin),
quit: make(chan bool),
}
}
// Start begins the interactive terminal session
func (t *TerminalInterface) Start() error {
t.printWelcomeMessage()
t.printHelp()
// Announce human agent presence
if err := t.announceHumanAgent(); err != nil {
t.runtime.Logger.Error("Failed to announce human agent presence: %v", err)
}
// Start command processing loop
go t.commandLoop()
// Wait for quit signal
<-t.quit
return nil
}
// Stop terminates the terminal interface
func (t *TerminalInterface) Stop() {
close(t.quit)
}
// printWelcomeMessage displays the HAP welcome screen
func (t *TerminalInterface) printWelcomeMessage() {
fmt.Println("\n" + strings.Repeat("=", 80))
fmt.Println("š CHORUS Human Agent Portal (HAP) - Terminal Interface")
fmt.Println(strings.Repeat("=", 80))
fmt.Printf("Agent ID: %s\n", t.runtime.Config.Agent.ID)
fmt.Printf("P2P Node: %s\n", t.runtime.Node.ID().ShortString())
fmt.Printf("Connected to: %d peers\n", t.runtime.Node.ConnectedPeers())
fmt.Println("\nYou are now connected to the CHORUS P2P agent network as a human participant.")
fmt.Println("You can collaborate with autonomous agents using the same protocols.")
fmt.Println(strings.Repeat("=", 80) + "\n")
}
// printHelp displays available commands
func (t *TerminalInterface) printHelp() {
fmt.Println("Available Commands:")
fmt.Println(" help - Show this help message")
fmt.Println(" status - Show network and agent status")
fmt.Println(" peers - List connected P2P peers")
fmt.Println(" hmmm - Compose and send HMMM reasoning message")
fmt.Println(" ucxl
- Browse UCXL context address")
fmt.Println(" patch - Create and submit patches")
fmt.Println(" collab - Collaborative editing sessions")
fmt.Println(" decide - Participate in distributed decision")
fmt.Println(" web - Start web bridge for browser access")
fmt.Println(" announce - Re-announce human agent presence")
fmt.Println(" quit - Exit HAP terminal")
fmt.Println()
}
// commandLoop handles user input and command processing
func (t *TerminalInterface) commandLoop() {
for {
fmt.Print("hap> ")
if !t.scanner.Scan() {
// EOF or error
break
}
input := strings.TrimSpace(t.scanner.Text())
if input == "" {
continue
}
parts := strings.Fields(input)
command := strings.ToLower(parts[0])
switch command {
case "help", "h":
t.printHelp()
case "status", "s":
t.printStatus()
case "peers":
t.listPeers()
case "hmmm", "m":
t.handleHMMMCommand(parts[1:])
case "ucxl", "u":
if len(parts) < 2 {
fmt.Println("Usage: ucxl ")
continue
}
t.handleUCXLCommand(parts[1])
case "patch", "p":
t.handlePatchCommand()
case "collab", "c":
t.handleCollaborativeEditingCommand()
case "decide", "d":
if len(parts) < 2 {
fmt.Println("Usage: decide ")
continue
}
topic := strings.Join(parts[1:], " ")
t.handleDecisionCommand(topic)
case "web", "w":
t.startWebBridge()
case "announce", "a":
if err := t.announceHumanAgent(); err != nil {
fmt.Printf("Failed to announce presence: %v\n", err)
} else {
fmt.Println("ā
Human agent presence announced to network")
}
case "quit", "q", "exit":
fmt.Println("š Goodbye! Disconnecting from CHORUS network...")
t.quit <- true
return
case "clear", "cls":
// Clear screen (works on most terminals)
fmt.Print("\033[2J\033[H")
t.printWelcomeMessage()
default:
fmt.Printf("Unknown command: %s\n", command)
fmt.Println("Type 'help' for available commands.")
}
}
}
// printStatus displays current network and agent status
func (t *TerminalInterface) printStatus() {
fmt.Println("\nš HAP Status Report")
fmt.Println(strings.Repeat("-", 40))
// Agent Info
fmt.Printf("Agent ID: %s\n", t.runtime.Config.Agent.ID)
fmt.Printf("Agent Role: %s\n", t.runtime.Config.Agent.Role)
fmt.Printf("Agent Type: Human (HAP)\n")
// P2P Network Status
fmt.Printf("Node ID: %s\n", t.runtime.Node.ID().ShortString())
fmt.Printf("Connected Peers: %d\n", t.runtime.Node.ConnectedPeers())
// Task Status
activeTasks := t.runtime.TaskTracker.GetActiveTasks()
maxTasks := t.runtime.TaskTracker.GetMaxTasks()
fmt.Printf("Active Tasks: %d/%d\n", len(activeTasks), maxTasks)
// DHT Status
if t.runtime.DHTNode != nil {
fmt.Printf("DHT: ā
Connected\n")
} else {
fmt.Printf("DHT: ā Disabled\n")
}
// BACKBEAT Status
if t.runtime.BackbeatIntegration != nil {
health := t.runtime.BackbeatIntegration.GetHealth()
if connected, ok := health["connected"].(bool); ok && connected {
fmt.Printf("BACKBEAT: ā
Connected\n")
} else {
fmt.Printf("BACKBEAT: ā ļø Disconnected\n")
}
} else {
fmt.Printf("BACKBEAT: ā Disabled\n")
}
fmt.Println(strings.Repeat("-", 40))
fmt.Printf("Last Updated: %s\n\n", time.Now().Format("15:04:05"))
}
// listPeers displays connected P2P peers
func (t *TerminalInterface) listPeers() {
peerCount := t.runtime.Node.ConnectedPeers()
fmt.Printf("\nš Connected P2P Peers (%d)\n", peerCount)
fmt.Println(strings.Repeat("-", 50))
if peerCount == 0 {
fmt.Println("No peers connected.")
fmt.Println("Ensure other CHORUS agents are running on the network.")
} else {
fmt.Printf("Connected to %d peer(s) in the CHORUS network.\n", peerCount)
fmt.Println("Use P2P discovery mechanisms to find autonomous agents.")
}
fmt.Println()
}
// announceHumanAgent broadcasts human agent presence to the network
func (t *TerminalInterface) announceHumanAgent() error {
presence := map[string]interface{}{
"agent_id": t.runtime.Config.Agent.ID,
"node_id": t.runtime.Node.ID().ShortString(),
"agent_type": "human",
"interface": "terminal",
"capabilities": []string{
"hmmm_reasoning",
"decision_making",
"context_browsing",
"collaborative_editing",
},
"human_operator": true,
"timestamp": time.Now().Unix(),
"status": "online",
}
// Publish to capability broadcast topic
if err := t.runtime.PubSub.PublishBzzzMessage(pubsub.CapabilityBcast, presence); err != nil {
return fmt.Errorf("failed to publish human agent announcement: %w", err)
}
t.runtime.Logger.Info("š¤ Human agent presence announced to network")
return nil
}
// handleHMMMCommand processes HMMM reasoning message composition
func (t *TerminalInterface) handleHMMMCommand(args []string) {
fmt.Println("\nš HMMM (Human-Machine-Machine-Machine) Message Composer")
fmt.Println(strings.Repeat("-", 60))
for {
fmt.Println("\nHMMM Commands:")
fmt.Println(" new - Compose new reasoning message")
fmt.Println(" reply - Reply to existing HMMM thread")
fmt.Println(" query - Ask network for reasoning help")
fmt.Println(" decide - Propose decision with reasoning")
fmt.Println(" help - Show detailed HMMM help")
fmt.Println(" back - Return to main HAP menu")
fmt.Print("\nhmmm> ")
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
fmt.Printf("Error reading input: %v\n", err)
continue
}
input = strings.TrimSpace(input)
if input == "" {
continue
}
if input == "back" || input == "exit" {
break
}
switch input {
case "help":
t.showHMMMHelp()
case "new":
t.composeNewHMMMMessage()
case "reply":
t.composeHMMMReply()
case "query":
t.composeHMMMQuery()
case "decide":
t.composeHMMMDecision()
default:
fmt.Println("Unknown HMMM command. Type 'help' for available commands.")
}
}
}
// handleUCXLCommand processes UCXL context browsing
func (t *TerminalInterface) handleUCXLCommand(address string) {
fmt.Printf("\nš UCXL Context Browser\n")
fmt.Println(strings.Repeat("-", 50))
// Parse the UCXL address
parsed, err := ucxl.ParseUCXLAddress(address)
if err != nil {
fmt.Printf("ā Invalid UCXL address: %v\n", err)
fmt.Println("\nValid format: ucxl://agent:role@project:task/path*temporal/")
fmt.Println("Example: ucxl://alice:dev@myproject:task123/docs/readme.md*^/")
t.showUCXLHelp()
return
}
fmt.Printf("š Address: %s\n", parsed.Raw)
fmt.Printf("š¤ Agent: %s\n", parsed.Agent)
fmt.Printf("š Role: %s\n", parsed.Role)
fmt.Printf("š Project: %s\n", parsed.Project)
fmt.Printf("š Task: %s\n", parsed.Task)
if parsed.Path != "" {
fmt.Printf("š Path: %s\n", parsed.Path)
}
if parsed.Temporal != "" {
fmt.Printf("ā° Temporal: %s\n", parsed.Temporal)
}
fmt.Println()
// Try to retrieve content from storage
if t.runtime.EncryptedStorage != nil {
content, metadata, err := t.runtime.EncryptedStorage.RetrieveUCXLContent(address)
if err != nil {
fmt.Printf("ā ļø Failed to retrieve content: %v\n", err)
fmt.Println("Content may not be available on this network.")
} else {
t.displayUCXLContent(content, metadata)
}
} else {
fmt.Println("ā ļø Storage system not available")
fmt.Println("Content retrieval requires configured DHT storage")
}
// Show UCXL browser commands
fmt.Println("\nUCXL Commands:")
fmt.Println(" search - Search for related content")
fmt.Println(" related - Find related contexts")
fmt.Println(" history - View address history")
fmt.Println(" create - Create new content at this address")
fmt.Println(" help - Show UCXL help")
fmt.Println(" back - Return to main menu")
for {
fmt.Print("\nucxl> ")
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
fmt.Printf("Error reading input: %v\n", err)
continue
}
input = strings.TrimSpace(input)
if input == "" {
continue
}
if input == "back" || input == "exit" {
break
}
switch input {
case "help":
t.showUCXLHelp()
case "search":
t.handleUCXLSearch(parsed)
case "related":
t.handleUCXLRelated(parsed)
case "history":
t.handleUCXLHistory(parsed)
case "create":
t.handleUCXLCreate(parsed)
default:
fmt.Println("Unknown UCXL command. Type 'help' for available commands.")
}
}
}
// handleDecisionCommand processes decision participation
func (t *TerminalInterface) handleDecisionCommand(topic string) {
fmt.Printf("\nš³ļø Decision Participation System\n")
fmt.Println(strings.Repeat("-", 50))
for {
fmt.Println("\nDecision Commands:")
fmt.Println(" list - List active decisions")
fmt.Println(" view - View decision details")
fmt.Println(" vote - Cast vote on decision")
fmt.Println(" propose - Propose new decision")
fmt.Println(" status - Show decision system status")
fmt.Println(" help - Show decision help")
fmt.Println(" back - Return to main menu")
fmt.Print("\ndecision> ")
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
fmt.Printf("Error reading input: %v\n", err)
continue
}
input = strings.TrimSpace(input)
if input == "" {
continue
}
if input == "back" || input == "exit" {
break
}
parts := strings.Fields(input)
command := parts[0]
switch command {
case "help":
t.showDecisionHelp()
case "list":
t.listActiveDecisions()
case "view":
if len(parts) < 2 {
fmt.Println("Usage: view ")
continue
}
t.viewDecision(parts[1])
case "vote":
if len(parts) < 2 {
fmt.Println("Usage: vote ")
continue
}
t.castVoteOnDecision(parts[1])
case "propose":
t.proposeNewDecision()
case "status":
t.showDecisionStatus()
default:
fmt.Println("Unknown decision command. Type 'help' for available commands.")
}
}
}
// HMMM Helper Functions
// showHMMMHelp displays detailed HMMM system information
func (t *TerminalInterface) showHMMMHelp() {
fmt.Println("\nš§ HMMM (Human-Machine-Machine-Machine) Collaborative Reasoning")
fmt.Println(strings.Repeat("=", 70))
fmt.Println("HMMM enables structured collaborative reasoning between humans and AI agents.")
fmt.Println("Messages are routed through the P2P network with rich metadata and context.")
fmt.Println()
fmt.Println("Message Types:")
fmt.Println(" new - Start a new reasoning thread on any topic")
fmt.Println(" reply - Respond to an existing thread with your reasoning")
fmt.Println(" query - Ask the network for help with a specific problem")
fmt.Println(" decide - Propose a decision that requires network consensus")
fmt.Println()
fmt.Println("Message Structure:")
fmt.Println(" ⢠Topic: Broad categorization (e.g., 'engineering', 'planning')")
fmt.Println(" ⢠Issue ID: Specific problem or discussion identifier")
fmt.Println(" ⢠Thread ID: Groups related messages together")
fmt.Println(" ⢠Message: Your human reasoning, insights, or questions")
fmt.Println(" ⢠Context: Links to relevant UCXL addresses or resources")
fmt.Println()
fmt.Println("Best Practices:")
fmt.Println(" ā
Be specific and clear in your reasoning")
fmt.Println(" ā
Include relevant context and background")
fmt.Println(" ā
Ask follow-up questions to guide discussion")
fmt.Println(" ā
Build on previous messages in the thread")
fmt.Println(" ā Avoid vague or overly broad statements")
fmt.Println(" ā Don't duplicate existing reasoning without adding value")
fmt.Println()
}
// composeNewHMMMMessage guides the user through creating a new reasoning message
func (t *TerminalInterface) composeNewHMMMMessage() {
fmt.Println("\nš New HMMM Reasoning Message")
fmt.Println(strings.Repeat("-", 40))
reader := bufio.NewReader(os.Stdin)
// Collect message details
fmt.Print("Topic (e.g., engineering, planning, architecture): ")
topic, _ := reader.ReadString('\n')
topic = strings.TrimSpace(topic)
if topic == "" {
topic = "general"
}
fmt.Print("Issue ID (number for this specific problem): ")
issueIDStr, _ := reader.ReadString('\n')
issueIDStr = strings.TrimSpace(issueIDStr)
var issueID int64 = 1
if issueIDStr != "" {
if id, err := strconv.ParseInt(issueIDStr, 10, 64); err == nil {
issueID = id
}
}
fmt.Print("Subject/Title: ")
subject, _ := reader.ReadString('\n')
subject = strings.TrimSpace(subject)
if subject == "" {
fmt.Println("ā Subject is required")
return
}
fmt.Println("Your reasoning (press Enter twice when done):")
var reasoning strings.Builder
emptyLines := 0
for {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
if line == "" {
emptyLines++
if emptyLines >= 2 {
break
}
reasoning.WriteString("\n")
} else {
emptyLines = 0
reasoning.WriteString(line + "\n")
}
}
if reasoning.Len() == 0 {
fmt.Println("ā Reasoning content is required")
return
}
// Generate message
msgID := t.generateMessageID()
threadID := t.generateThreadID(topic, issueID)
message := hmmm.Message{
Topic: fmt.Sprintf("CHORUS/hmmm/%s", topic),
Type: "reasoning_start",
Payload: map[string]interface{}{
"subject": subject,
"reasoning": strings.TrimSpace(reasoning.String()),
"author": t.runtime.Config.Agent.ID,
"author_type": "human",
},
Version: "1.0",
IssueID: issueID,
ThreadID: threadID,
MsgID: msgID,
NodeID: t.runtime.Node.ID().String(),
HopCount: 0,
Timestamp: time.Now().Unix(),
Message: fmt.Sprintf("New reasoning thread: %s", subject),
}
// Send message
if err := t.sendHMMMMessage(message); err != nil {
fmt.Printf("ā Failed to send HMMM message: %v\n", err)
return
}
fmt.Println("ā
HMMM reasoning message sent to network")
fmt.Printf(" Topic: %s\n", topic)
fmt.Printf(" Issue: #%d\n", issueID)
fmt.Printf(" Thread: %s\n", threadID)
fmt.Printf(" Message ID: %s\n", msgID)
fmt.Println()
}
// composeHMMMReply guides the user through replying to an existing thread
func (t *TerminalInterface) composeHMMMReply() {
fmt.Println("\nā©ļø Reply to HMMM Thread")
fmt.Println(strings.Repeat("-", 30))
reader := bufio.NewReader(os.Stdin)
fmt.Print("Thread ID to reply to: ")
threadID, _ := reader.ReadString('\n')
threadID = strings.TrimSpace(threadID)
if threadID == "" {
fmt.Println("ā Thread ID is required")
return
}
fmt.Print("Issue ID: ")
issueIDStr, _ := reader.ReadString('\n')
issueIDStr = strings.TrimSpace(issueIDStr)
var issueID int64 = 1
if issueIDStr != "" {
if id, err := strconv.ParseInt(issueIDStr, 10, 64); err == nil {
issueID = id
}
}
fmt.Println("Your reasoning/response (press Enter twice when done):")
var reasoning strings.Builder
emptyLines := 0
for {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
if line == "" {
emptyLines++
if emptyLines >= 2 {
break
}
reasoning.WriteString("\n")
} else {
emptyLines = 0
reasoning.WriteString(line + "\n")
}
}
if reasoning.Len() == 0 {
fmt.Println("ā Response content is required")
return
}
msgID := t.generateMessageID()
message := hmmm.Message{
Topic: fmt.Sprintf("CHORUS/hmmm/thread/%s", threadID),
Type: "reasoning_reply",
Payload: map[string]interface{}{
"reasoning": strings.TrimSpace(reasoning.String()),
"author": t.runtime.Config.Agent.ID,
"author_type": "human",
"parent_thread": threadID,
},
Version: "1.0",
IssueID: issueID,
ThreadID: threadID,
MsgID: msgID,
NodeID: t.runtime.Node.ID().String(),
HopCount: 0,
Timestamp: time.Now().Unix(),
Message: "Human agent reasoning response",
}
if err := t.sendHMMMMessage(message); err != nil {
fmt.Printf("ā Failed to send HMMM reply: %v\n", err)
return
}
fmt.Println("ā
HMMM reply sent to thread")
fmt.Printf(" Thread: %s\n", threadID)
fmt.Printf(" Message ID: %s\n", msgID)
fmt.Println()
}
// composeHMMMQuery guides the user through asking for reasoning help
func (t *TerminalInterface) composeHMMMQuery() {
fmt.Println("\nā HMMM Network Query")
fmt.Println(strings.Repeat("-", 25))
reader := bufio.NewReader(os.Stdin)
fmt.Print("Query topic (e.g., technical, planning): ")
topic, _ := reader.ReadString('\n')
topic = strings.TrimSpace(topic)
if topic == "" {
topic = "general"
}
fmt.Print("Issue ID (or press Enter for new): ")
issueIDStr, _ := reader.ReadString('\n')
issueIDStr = strings.TrimSpace(issueIDStr)
var issueID int64
if issueIDStr != "" {
if id, err := strconv.ParseInt(issueIDStr, 10, 64); err == nil {
issueID = id
}
} else {
// Generate new issue ID
issueID = time.Now().Unix() % 10000
}
fmt.Print("Your question/problem: ")
question, _ := reader.ReadString('\n')
question = strings.TrimSpace(question)
if question == "" {
fmt.Println("ā Question is required")
return
}
fmt.Println("Additional context (press Enter twice when done, or just Enter to skip):")
var context strings.Builder
emptyLines := 0
for {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
if line == "" {
emptyLines++
if emptyLines >= 2 {
break
}
if context.Len() > 0 {
context.WriteString("\n")
}
} else {
emptyLines = 0
if context.Len() > 0 {
context.WriteString(" ")
}
context.WriteString(line)
}
}
msgID := t.generateMessageID()
threadID := t.generateThreadID(topic, issueID)
message := hmmm.Message{
Topic: fmt.Sprintf("CHORUS/hmmm/query/%s", topic),
Type: "reasoning_query",
Payload: map[string]interface{}{
"question": question,
"context": context.String(),
"author": t.runtime.Config.Agent.ID,
"author_type": "human",
"urgency": "normal",
},
Version: "1.0",
IssueID: issueID,
ThreadID: threadID,
MsgID: msgID,
NodeID: t.runtime.Node.ID().String(),
HopCount: 0,
Timestamp: time.Now().Unix(),
Message: fmt.Sprintf("Human query: %s", question),
}
if err := t.sendHMMMMessage(message); err != nil {
fmt.Printf("ā Failed to send HMMM query: %v\n", err)
return
}
fmt.Println("ā
HMMM query sent to network")
fmt.Printf(" Waiting for agent responses on issue #%d\n", issueID)
fmt.Printf(" Thread: %s\n", threadID)
fmt.Printf(" Message ID: %s\n", msgID)
fmt.Println()
}
// composeHMMMDecision guides the user through proposing a decision
func (t *TerminalInterface) composeHMMMDecision() {
fmt.Println("\nš³ļø Propose Network Decision")
fmt.Println(strings.Repeat("-", 30))
reader := bufio.NewReader(os.Stdin)
fmt.Print("Decision topic: ")
topic, _ := reader.ReadString('\n')
topic = strings.TrimSpace(topic)
if topic == "" {
topic = "general"
}
fmt.Print("Decision title: ")
title, _ := reader.ReadString('\n')
title = strings.TrimSpace(title)
if title == "" {
fmt.Println("ā Decision title is required")
return
}
fmt.Println("Decision rationale (press Enter twice when done):")
var rationale strings.Builder
emptyLines := 0
for {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
if line == "" {
emptyLines++
if emptyLines >= 2 {
break
}
rationale.WriteString("\n")
} else {
emptyLines = 0
rationale.WriteString(line + "\n")
}
}
if rationale.Len() == 0 {
fmt.Println("ā Rationale is required")
return
}
fmt.Print("Options (comma-separated, e.g., 'approve,reject,defer'): ")
optionsStr, _ := reader.ReadString('\n')
optionsStr = strings.TrimSpace(optionsStr)
options := strings.Split(optionsStr, ",")
if len(options) == 0 {
options = []string{"approve", "reject"}
}
for i := range options {
options[i] = strings.TrimSpace(options[i])
}
issueID := time.Now().Unix() % 10000
msgID := t.generateMessageID()
threadID := t.generateThreadID("decision", issueID)
message := hmmm.Message{
Topic: fmt.Sprintf("CHORUS/hmmm/decision/%s", topic),
Type: "decision_proposal",
Payload: map[string]interface{}{
"title": title,
"rationale": strings.TrimSpace(rationale.String()),
"options": options,
"proposer": t.runtime.Config.Agent.ID,
"author_type": "human",
"deadline": time.Now().Add(24 * time.Hour).Unix(),
},
Version: "1.0",
IssueID: issueID,
ThreadID: threadID,
MsgID: msgID,
NodeID: t.runtime.Node.ID().String(),
HopCount: 0,
Timestamp: time.Now().Unix(),
Message: fmt.Sprintf("Decision proposal: %s", title),
}
if err := t.sendHMMMMessage(message); err != nil {
fmt.Printf("ā Failed to send decision proposal: %v\n", err)
return
}
fmt.Println("ā
Decision proposal sent to network")
fmt.Printf(" Title: %s\n", title)
fmt.Printf(" Issue: #%d\n", issueID)
fmt.Printf(" Options: %s\n", strings.Join(options, ", "))
fmt.Printf(" Thread: %s\n", threadID)
fmt.Printf(" Deadline: 24 hours from now\n")
fmt.Println()
}
// Helper functions for HMMM message management
// sendHMMMMessage sends an HMMM message through the P2P network
func (t *TerminalInterface) sendHMMMMessage(message hmmm.Message) error {
router := hmmm.NewRouter(t.runtime.PubSub)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
return router.Publish(ctx, message)
}
// generateMessageID creates a unique message identifier
func (t *TerminalInterface) generateMessageID() string {
// Generate a random component
randomNum, _ := rand.Int(rand.Reader, big.NewInt(999999))
timestamp := time.Now().UnixNano()
return fmt.Sprintf("hap-%d-%06d", timestamp/1000000, randomNum.Int64())
}
// generateThreadID creates a thread identifier for grouping related messages
func (t *TerminalInterface) generateThreadID(topic string, issueID int64) string {
hash := fmt.Sprintf("%s-%d-%d", topic, issueID, time.Now().Unix()/3600) // Hour-based grouping
return fmt.Sprintf("thread-%x", hash)
}
// UCXL Helper Functions
// showUCXLHelp displays detailed UCXL system information
func (t *TerminalInterface) showUCXLHelp() {
fmt.Println("\nšŗļø UCXL (Universal Context Exchange Language)")
fmt.Println(strings.Repeat("=", 60))
fmt.Println("UCXL provides addressing and navigation for distributed contexts.")
fmt.Println("Each address uniquely identifies content, resources, or state.")
fmt.Println()
fmt.Println("Address Format:")
fmt.Println(" ucxl://agent:role@project:task/path*temporal/")
fmt.Println()
fmt.Println("Components:")
fmt.Println(" agent - Agent ID or '*' for wildcard")
fmt.Println(" role - Agent role (dev, admin, user, etc.)")
fmt.Println(" project - Project identifier")
fmt.Println(" task - Task or issue identifier")
fmt.Println(" path - Optional resource path")
fmt.Println(" temporal - Optional time navigation")
fmt.Println()
fmt.Println("Temporal Navigation:")
fmt.Println(" *^/ - Latest version")
fmt.Println(" *~/ - Earliest version")
fmt.Println(" *@1234/ - Specific timestamp")
fmt.Println(" *~5/ - 5 versions back")
fmt.Println(" *^3/ - 3 versions forward")
fmt.Println()
fmt.Println("Examples:")
fmt.Println(" ucxl://alice:dev@webapp:frontend/src/components/")
fmt.Println(" ucxl://*:*@project123:bug456/logs/error.log*^/")
fmt.Println(" ucxl://bob:admin@infra:deploy/config/prod.yml*@1609459200/")
fmt.Println()
}
// displayUCXLContent shows retrieved content with metadata
func (t *TerminalInterface) displayUCXLContent(content []byte, metadata *storage.UCXLMetadata) {
fmt.Println("š¦ Content Found:")
fmt.Println(strings.Repeat("-", 30))
if metadata != nil {
fmt.Printf("š Type: %s\n", metadata.ContentType)
fmt.Printf("š¤ Creator: %s\n", metadata.CreatorRole)
fmt.Printf("š
Created: %s\n", metadata.CreatedAt.Format("2006-01-02 15:04:05"))
fmt.Printf("š Size: %d bytes\n", metadata.Size)
if metadata.Encrypted {
fmt.Printf("š Encrypted: Yes\n")
}
fmt.Println()
}
// Show content preview
contentStr := string(content)
if len(contentStr) > 1000 {
fmt.Printf("š Content Preview (first 1000 chars):\n%s\n...(truncated)\n", contentStr[:1000])
} else {
fmt.Printf("š Content:\n%s\n", contentStr)
}
fmt.Println()
}
// handleUCXLSearch searches for related UCXL content
func (t *TerminalInterface) handleUCXLSearch(parsed *ucxl.UCXLAddress) {
fmt.Println("\nš Search UCXL Content")
fmt.Println(strings.Repeat("-", 30))
if t.runtime.EncryptedStorage == nil {
fmt.Println("ā Storage system not available")
return
}
reader := bufio.NewReader(os.Stdin)
// Build search query from current address
query := &storage.SearchQuery{
Agent: parsed.Agent,
Role: parsed.Role,
Project: parsed.Project,
Task: parsed.Task,
Limit: 20,
}
// Allow user to modify search criteria
fmt.Print("Search agent (current: " + parsed.Agent + ", or press Enter): ")
input, _ := reader.ReadString('\n')
input = strings.TrimSpace(input)
if input != "" {
query.Agent = input
}
fmt.Print("Search role (current: " + parsed.Role + ", or press Enter): ")
input, _ = reader.ReadString('\n')
input = strings.TrimSpace(input)
if input != "" {
query.Role = input
}
fmt.Print("Search project (current: " + parsed.Project + ", or press Enter): ")
input, _ = reader.ReadString('\n')
input = strings.TrimSpace(input)
if input != "" {
query.Project = input
}
fmt.Print("Content type filter (optional): ")
contentType, _ := reader.ReadString('\n')
contentType = strings.TrimSpace(contentType)
if contentType != "" {
query.ContentType = contentType
}
// Perform search
results, err := t.runtime.EncryptedStorage.SearchContent(query)
if err != nil {
fmt.Printf("ā Search failed: %v\n", err)
return
}
fmt.Printf("\nš Found %d results:\n", len(results))
fmt.Println(strings.Repeat("-", 50))
for i, result := range results {
fmt.Printf("%d. %s\n", i+1, result.Address)
fmt.Printf(" š Type: %s | š¤ Creator: %s | š
%s\n",
result.ContentType,
result.CreatorRole,
result.CreatedAt.Format("2006-01-02 15:04"))
fmt.Println()
}
}
// handleUCXLRelated finds content related to the current address
func (t *TerminalInterface) handleUCXLRelated(parsed *ucxl.UCXLAddress) {
fmt.Println("\nš Find Related Content")
fmt.Println(strings.Repeat("-", 25))
if t.runtime.EncryptedStorage == nil {
fmt.Println("ā Storage system not available")
return
}
// Search for content with same project and task
query := &storage.SearchQuery{
Agent: "*",
Role: "*",
Project: parsed.Project,
Task: parsed.Task,
Limit: 10,
}
results, err := t.runtime.EncryptedStorage.SearchContent(query)
if err != nil {
fmt.Printf("ā Related search failed: %v\n", err)
return
}
fmt.Printf("š Related content in %s:%s:\n", parsed.Project, parsed.Task)
fmt.Println(strings.Repeat("-", 40))
for i, result := range results {
if result.Address == parsed.Raw {
continue // Skip current address
}
fmt.Printf("%d. %s\n", i+1, result.Address)
fmt.Printf(" š¤ %s | š %s | š
%s\n",
result.CreatorRole,
result.ContentType,
result.CreatedAt.Format("Jan 02, 15:04"))
}
if len(results) <= 1 {
fmt.Println("No related content found.")
fmt.Println("Try creating content or using broader search terms.")
}
fmt.Println()
}
// handleUCXLHistory shows version history for the address
func (t *TerminalInterface) handleUCXLHistory(parsed *ucxl.UCXLAddress) {
fmt.Println("\nš Address History")
fmt.Println(strings.Repeat("-", 20))
fmt.Println("ā ļø History tracking not yet fully implemented")
fmt.Println("This would show temporal versions of the content:")
fmt.Println()
fmt.Printf("Base address: %s\n", parsed.Raw)
fmt.Println("Temporal versions:")
fmt.Printf(" Latest: %s*^/\n", strings.TrimSuffix(parsed.Raw, "/"))
fmt.Printf(" Earliest: %s*~/\n", strings.TrimSuffix(parsed.Raw, "/"))
fmt.Printf(" Previous: %s*~1/\n", strings.TrimSuffix(parsed.Raw, "/"))
fmt.Printf(" Timestamp: %s*@%d/\n", strings.TrimSuffix(parsed.Raw, "/"), time.Now().Unix())
fmt.Println()
}
// handleUCXLCreate helps create new content at the address
func (t *TerminalInterface) handleUCXLCreate(parsed *ucxl.UCXLAddress) {
fmt.Println("\nš Create UCXL Content")
fmt.Println(strings.Repeat("-", 25))
if t.runtime.EncryptedStorage == nil {
fmt.Println("ā Storage system not available")
return
}
reader := bufio.NewReader(os.Stdin)
fmt.Print("Content type (text/plain, application/json, etc.): ")
contentType, _ := reader.ReadString('\n')
contentType = strings.TrimSpace(contentType)
if contentType == "" {
contentType = "text/plain"
}
fmt.Println("Content (press Enter twice when done):")
var content strings.Builder
emptyLines := 0
for {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
if line == "" {
emptyLines++
if emptyLines >= 2 {
break
}
content.WriteString("\n")
} else {
emptyLines = 0
content.WriteString(line + "\n")
}
}
contentBytes := []byte(strings.TrimSpace(content.String()))
if len(contentBytes) == 0 {
fmt.Println("ā No content provided")
return
}
// Store content
err := t.runtime.EncryptedStorage.StoreUCXLContent(
parsed.Raw,
contentBytes,
t.runtime.Config.Agent.Role,
contentType,
)
if err != nil {
fmt.Printf("ā Failed to store content: %v\n", err)
return
}
// Announce to network
if err := t.runtime.EncryptedStorage.AnnounceContent(parsed.Raw); err != nil {
fmt.Printf("ā ļø Failed to announce content: %v\n", err)
}
fmt.Println("ā
Content created successfully!")
fmt.Printf(" Address: %s\n", parsed.Raw)
fmt.Printf(" Type: %s\n", contentType)
fmt.Printf(" Size: %d bytes\n", len(contentBytes))
fmt.Println(" Content announced to P2P network")
fmt.Println()
}
// handleCollaborativeEditingCommand processes collaborative editing sessions
func (t *TerminalInterface) handleCollaborativeEditingCommand() {
fmt.Printf("\nš„ CHORUS Collaborative Editing System\n")
fmt.Println(strings.Repeat("-", 50))
for {
fmt.Println("\nCollaborative Editing Commands:")
fmt.Println(" start - Start collaborative session on UCXL address")
fmt.Println(" join - Join existing collaborative session")
fmt.Println(" list - List active collaborative sessions")
fmt.Println(" status - Show collaborative editing status")
fmt.Println(" leave - Leave current collaborative session")
fmt.Println(" help - Show collaborative editing help")
fmt.Println(" back - Return to main menu")
fmt.Print("\ncollab> ")
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
fmt.Printf("Error reading input: %v\n", err)
continue
}
input = strings.TrimSpace(input)
if input == "" {
continue
}
if input == "back" || input == "exit" {
break
}
parts := strings.Fields(input)
command := parts[0]
switch command {
case "help":
t.showCollaborativeEditingHelp()
case "start":
if len(parts) < 2 {
fmt.Println("Usage: start ")
continue
}
t.startCollaborativeSession(parts[1])
case "join":
if len(parts) < 2 {
fmt.Println("Usage: join ")
continue
}
t.joinCollaborativeSession(parts[1])
case "list":
t.listCollaborativeSessions()
case "status":
t.showCollaborativeEditingStatus()
case "leave":
t.leaveCollaborativeSession()
default:
fmt.Println("Unknown collaborative editing command. Type 'help' for available commands.")
}
}
}
// handlePatchCommand processes patch creation and submission workflows
func (t *TerminalInterface) handlePatchCommand() {
fmt.Printf("\nš CHORUS Patch Management System\n")
fmt.Println(strings.Repeat("-", 50))
for {
fmt.Println("\nPatch Commands:")
fmt.Println(" create - Create new patch from current state")
fmt.Println(" diff - Generate diff for context changes")
fmt.Println(" submit - Submit patch for review and integration")
fmt.Println(" list - List active patches")
fmt.Println(" review - Review existing patches")
fmt.Println(" status - Show patch system status")
fmt.Println(" help - Show patch system help")
fmt.Println(" back - Return to main menu")
fmt.Print("\npatch> ")
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
fmt.Printf("Error reading input: %v\n", err)
continue
}
input = strings.TrimSpace(input)
if input == "" {
continue
}
if input == "back" || input == "exit" {
break
}
switch input {
case "help":
t.showPatchHelp()
case "create":
t.createPatch()
case "diff":
t.generateDiff()
case "submit":
t.submitPatch()
case "list":
t.listPatches()
case "review":
t.reviewPatches()
case "status":
t.showPatchStatus()
default:
fmt.Println("Unknown patch command. Type 'help' for available commands.")
}
}
}
// Decision Participation Helper Functions
// showDecisionHelp displays detailed decision system information
func (t *TerminalInterface) showDecisionHelp() {
fmt.Println("\nš³ļø CHORUS Distributed Decision System")
fmt.Println(strings.Repeat("=", 55))
fmt.Println("The decision system enables collaborative consensus among network participants.")
fmt.Println("Both human agents and autonomous agents can participate in decision-making.")
fmt.Println()
fmt.Println("Decision Types:")
fmt.Println(" ⢠Technical: Architecture, implementation choices")
fmt.Println(" ⢠Operational: Resource allocation, task priority")
fmt.Println(" ⢠Policy: Network rules, behavioral guidelines")
fmt.Println(" ⢠Emergency: Urgent security or stability issues")
fmt.Println()
fmt.Println("Vote Options:")
fmt.Println(" ā
approve - Support the proposed decision")
fmt.Println(" ā reject - Oppose the proposed decision")
fmt.Println(" āøļø defer - Postpone decision to gather more info")
fmt.Println(" ā ļø abstain - Acknowledge but not participate")
fmt.Println()
fmt.Println("Consensus Rules:")
fmt.Println(" ⢠Majority approval required for most decisions")
fmt.Println(" ⢠Supermajority (2/3) for critical infrastructure changes")
fmt.Println(" ⢠Emergency decisions may have shorter time windows")
fmt.Println(" ⢠All votes should include reasoning/justification")
fmt.Println()
fmt.Println("Commands:")
fmt.Println(" list - See all active decisions awaiting votes")
fmt.Println(" view - View full decision details and current voting")
fmt.Println(" vote - Cast your vote with reasoning")
fmt.Println(" propose - Start a new decision for network consideration")
fmt.Println()
}
// listActiveDecisions shows all decisions currently open for voting
func (t *TerminalInterface) listActiveDecisions() {
fmt.Println("\nš Active Network Decisions")
fmt.Println(strings.Repeat("-", 35))
// Query DHT for active decisions
decisions, err := t.getActiveDecisions()
if err != nil {
fmt.Printf("ā Failed to retrieve decisions: %v\n", err)
return
}
if len(decisions) == 0 {
fmt.Println("ā
No active decisions requiring votes")
fmt.Println("\nš” Use 'propose' to create a new decision")
return
}
fmt.Printf("Found %d active decision(s):\n\n", len(decisions))
for _, decision := range decisions {
statusEmoji := "š³ļø"
if decision.Status == "urgent" {
statusEmoji = "šØ"
} else if decision.Status == "closed" {
statusEmoji = "ā
"
}
// Calculate time remaining
timeRemaining := decision.Deadline.Sub(time.Now())
timeStr := formatDuration(timeRemaining)
// Count votes
approvals := 0
rejections := 0
deferrals := 0
abstentions := 0
for _, vote := range decision.Votes {
switch vote.Vote {
case "approve":
approvals++
case "reject":
rejections++
case "defer":
deferrals++
case "abstain":
abstentions++
}
}
fmt.Printf("%s %s - %s\n", statusEmoji, decision.ID, decision.Title)
fmt.Printf(" š Type: %s | š¤ Proposer: %s (%s)\n",
decision.Type, decision.Proposer, decision.ProposerType)
fmt.Printf(" ā° Time left: %s | š³ļø Votes: ā
%d ā%d āøļø%d ā ļø%d\n",
timeStr, approvals, rejections, deferrals, abstentions)
fmt.Println()
}
fmt.Println("Use 'view ' to see full details and cast your vote.")
fmt.Println("Example: view DEC-001")
fmt.Println()
}
// viewDecision shows detailed information about a specific decision
func (t *TerminalInterface) viewDecision(decisionID string) {
fmt.Printf("\nš Decision Details: %s\n", decisionID)
fmt.Println(strings.Repeat("-", 40))
decision, err := t.getDecisionByID(decisionID)
if err != nil {
fmt.Printf("ā Failed to retrieve decision: %v\n", err)
return
}
fmt.Printf("š Title: %s\n", decision.Title)
fmt.Printf("š·ļø Type: %s\n", strings.Title(decision.Type))
fmt.Printf("š¤ Proposer: %s (%s)\n", decision.Proposer, decision.ProposerType)
fmt.Printf("š
Proposed: %s\n", decision.CreatedAt.Format("2006-01-02 15:04:05"))
timeRemaining := decision.Deadline.Sub(time.Now())
fmt.Printf("ā° Deadline: %s (%s remaining)\n",
decision.Deadline.Format("2006-01-02 15:04:05"),
formatDuration(timeRemaining))
fmt.Println()
fmt.Println("š Description:")
wrapped := wrapText(decision.Description, 60)
for _, line := range strings.Split(wrapped, "\n") {
fmt.Printf(" %s\n", line)
}
fmt.Println()
fmt.Printf("š³ļø Current Voting Status (%d total votes):\n", len(decision.Votes))
// Count votes by type
approvals := 0
rejections := 0
deferrals := 0
abstentions := 0
for _, vote := range decision.Votes {
switch vote.Vote {
case "approve":
approvals++
case "reject":
rejections++
case "defer":
deferrals++
case "abstain":
abstentions++
}
}
fmt.Printf(" ā
Approve: %d votes\n", approvals)
fmt.Printf(" ā Reject: %d votes\n", rejections)
fmt.Printf(" āøļø Defer: %d votes\n", deferrals)
fmt.Printf(" ā ļø Abstain: %d votes\n", abstentions)
if len(decision.Votes) > 0 {
fmt.Println("\nš Recent Reasoning:")
count := 0
for _, vote := range decision.Votes {
if count >= 3 { // Show only last 3 votes
break
}
fmt.Printf(" %s (%s): \"%s\"\n", vote.VoterID, vote.Vote, vote.Reasoning)
count++
}
}
// Calculate status
totalVotes := len(decision.Votes)
if totalVotes > 0 {
approvalRate := float64(approvals) / float64(totalVotes) * 100
fmt.Printf("\nšÆ Status: %.1f%% approval", approvalRate)
if approvalRate >= 50 {
fmt.Print(" (Passing)")
} else {
fmt.Print(" (Failing)")
}
fmt.Println()
}
// Show metadata if present
if len(decision.Metadata) > 0 {
fmt.Println("\nš Metadata:")
for key, value := range decision.Metadata {
fmt.Printf(" %s: %v\n", key, value)
}
}
fmt.Println()
fmt.Printf("To vote on this decision, use: vote %s\n", decisionID)
fmt.Println()
}
// castVoteOnDecision guides the user through voting on a decision
func (t *TerminalInterface) castVoteOnDecision(decisionID string) {
fmt.Printf("\nš³ļø Cast Vote on %s\n", decisionID)
fmt.Println(strings.Repeat("-", 30))
reader := bufio.NewReader(os.Stdin)
// Show vote options
fmt.Println("Vote Options:")
fmt.Println(" 1. ā
approve - Support this decision")
fmt.Println(" 2. ā reject - Oppose this decision")
fmt.Println(" 3. āøļø defer - Need more information")
fmt.Println(" 4. ā ļø abstain - Acknowledge but not participate")
fmt.Println()
fmt.Print("Your vote (1-4): ")
voteInput, _ := reader.ReadString('\n')
voteInput = strings.TrimSpace(voteInput)
var vote string
switch voteInput {
case "1", "approve":
vote = "approve"
case "2", "reject":
vote = "reject"
case "3", "defer":
vote = "defer"
case "4", "abstain":
vote = "abstain"
default:
fmt.Println("ā Invalid vote option. Please choose 1-4.")
return
}
fmt.Printf("You selected: %s\n", vote)
fmt.Println()
// Get reasoning/justification
fmt.Println("Reasoning/Justification (required for transparency):")
fmt.Println("Explain why you are voting this way (press Enter twice when done):")
var reasoning strings.Builder
emptyLines := 0
for {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
if line == "" {
emptyLines++
if emptyLines >= 2 {
break
}
reasoning.WriteString("\n")
} else {
emptyLines = 0
reasoning.WriteString(line + "\n")
}
}
reasoningText := strings.TrimSpace(reasoning.String())
if reasoningText == "" {
fmt.Println("ā Reasoning is required for all votes")
return
}
// Confirmation
fmt.Println("š Vote Summary:")
fmt.Printf(" Decision: %s\n", decisionID)
fmt.Printf(" Your Vote: %s\n", vote)
fmt.Printf(" Reasoning: %s\n", reasoningText)
fmt.Println()
fmt.Print("Submit this vote? (y/n): ")
confirm, _ := reader.ReadString('\n')
confirm = strings.TrimSpace(strings.ToLower(confirm))
if confirm != "y" && confirm != "yes" {
fmt.Println("ā Vote cancelled")
return
}
// Submit vote to decision system
fmt.Println("š Submitting vote...")
// Get current decision to update it
decision, err := t.getDecisionByID(decisionID)
if err != nil {
fmt.Printf("ā Failed to retrieve decision: %v\n", err)
return
}
// Create vote record
voteRecord := DecisionVote{
VoterID: t.runtime.Config.Agent.ID,
VoterType: "human",
Vote: vote,
Reasoning: reasoningText,
Timestamp: time.Now(),
Confidence: 1.0, // Human votes have full confidence
}
// Add/update vote in decision
if decision.Votes == nil {
decision.Votes = make(map[string]DecisionVote)
}
decision.Votes[t.runtime.Config.Agent.ID] = voteRecord
decision.Version++
// Save updated decision
if err := t.saveDecision(decision); err != nil {
fmt.Printf("ā Failed to save vote: %v\n", err)
return
}
// Announce vote via HMMM
if err := t.announceDecisionVote(decisionID, voteRecord); err != nil {
fmt.Printf("ā ļø Failed to announce vote via HMMM: %v\n", err)
} else {
fmt.Println("š¢ Vote announced via HMMM reasoning network")
}
fmt.Printf("ā
Your %s vote on %s has been recorded\n", vote, decisionID)
fmt.Println("š Vote reasoning published to network for transparency")
fmt.Println("š Other network members will be notified of your participation")
fmt.Println()
}
// proposeNewDecision guides the user through creating a new decision
func (t *TerminalInterface) proposeNewDecision() {
fmt.Println("\nš Propose New Network Decision")
fmt.Println(strings.Repeat("-", 35))
reader := bufio.NewReader(os.Stdin)
// Decision type
fmt.Println("Decision Types:")
fmt.Println(" 1. technical - Architecture, code, infrastructure")
fmt.Println(" 2. operational - Process, resource allocation")
fmt.Println(" 3. policy - Network rules, governance")
fmt.Println(" 4. emergency - Urgent security/stability issue")
fmt.Println()
fmt.Print("Decision type (1-4): ")
typeInput, _ := reader.ReadString('\n')
typeInput = strings.TrimSpace(typeInput)
var decisionType string
switch typeInput {
case "1", "technical":
decisionType = "technical"
case "2", "operational":
decisionType = "operational"
case "3", "policy":
decisionType = "policy"
case "4", "emergency":
decisionType = "emergency"
default:
fmt.Println("ā Invalid decision type")
return
}
// Title
fmt.Print("Decision title (concise summary): ")
title, _ := reader.ReadString('\n')
title = strings.TrimSpace(title)
if title == "" {
fmt.Println("ā Title is required")
return
}
// Rationale
fmt.Println("Detailed rationale (press Enter twice when done):")
var rationale strings.Builder
emptyLines := 0
for {
line, _ := reader.ReadString('\n')
line = strings.TrimSpace(line)
if line == "" {
emptyLines++
if emptyLines >= 2 {
break
}
rationale.WriteString("\n")
} else {
emptyLines = 0
rationale.WriteString(line + "\n")
}
}
rationaleText := strings.TrimSpace(rationale.String())
if rationaleText == "" {
fmt.Println("ā Rationale is required")
return
}
// Voting options
fmt.Print("Custom voting options (comma-separated, or press Enter for default): ")
optionsInput, _ := reader.ReadString('\n')
optionsInput = strings.TrimSpace(optionsInput)
var options []string
if optionsInput == "" {
options = []string{"approve", "reject", "defer", "abstain"}
} else {
options = strings.Split(optionsInput, ",")
for i := range options {
options[i] = strings.TrimSpace(options[i])
}
}
// Deadline
var deadline time.Duration
if decisionType == "emergency" {
deadline = 2 * time.Hour
fmt.Println("ā ļø Emergency decisions have 2-hour deadline")
} else {
fmt.Print("Voting deadline in hours (default: 24): ")
deadlineInput, _ := reader.ReadString('\n')
deadlineInput = strings.TrimSpace(deadlineInput)
if deadlineInput == "" {
deadline = 24 * time.Hour
} else {
hours, err := strconv.ParseFloat(deadlineInput, 64)
if err != nil || hours <= 0 {
fmt.Println("ā Invalid deadline")
return
}
deadline = time.Duration(hours * float64(time.Hour))
}
}
// Summary and confirmation
fmt.Println("\nš Decision Proposal Summary:")
fmt.Printf(" Type: %s\n", decisionType)
fmt.Printf(" Title: %s\n", title)
fmt.Printf(" Options: %s\n", strings.Join(options, ", "))
fmt.Printf(" Deadline: %s from now\n", deadline)
fmt.Printf(" Rationale:\n%s\n", rationaleText)
fmt.Println()
fmt.Print("Submit this decision proposal? (y/n): ")
confirm, _ := reader.ReadString('\n')
confirm = strings.TrimSpace(strings.ToLower(confirm))
if confirm != "y" && confirm != "yes" {
fmt.Println("ā Decision proposal cancelled")
return
}
// Generate decision ID
decisionID := fmt.Sprintf("DEC-%s", generateRandomID(6))
// Create decision object
decision := &Decision{
ID: decisionID,
Title: title,
Description: rationaleText,
Type: decisionType,
Proposer: t.runtime.Config.Agent.ID,
ProposerType: "human",
CreatedAt: time.Now(),
Deadline: time.Now().Add(deadline),
Status: "voting",
Votes: make(map[string]DecisionVote),
Metadata: map[string]interface{}{
"voting_options": options,
"priority": "normal",
},
Version: 1,
}
if decisionType == "emergency" {
decision.Metadata["priority"] = "urgent"
decision.Status = "urgent"
}
// Save decision to DHT
fmt.Println("š Creating decision proposal...")
if err := t.saveDecision(decision); err != nil {
fmt.Printf("ā Failed to create decision: %v\n", err)
return
}
// Send HMMM announcement
if err := t.announceDecisionProposal(decision); err != nil {
fmt.Printf("ā ļø Failed to announce via HMMM: %v\n", err)
} else {
fmt.Println("š” Decision announced via HMMM reasoning network")
}
fmt.Printf("ā
Decision %s proposed successfully\n", decisionID)
fmt.Println("š¢ Decision announced to all network members")
fmt.Printf("ā° Voting closes in %s\n", deadline)
fmt.Println("š³ļø Network members can now cast their votes")
fmt.Println()
}
// showDecisionStatus shows overall decision system status
func (t *TerminalInterface) showDecisionStatus() {
fmt.Println("\nš Decision System Status")
fmt.Println(strings.Repeat("-", 30))
fmt.Println("ā ļø Decision system integration in development")
fmt.Println()
fmt.Println("Mock system status:")
fmt.Printf("š³ļø Active Decisions: 3\n")
fmt.Printf("ā° Urgent Decisions: 1 (emergency timeout)\n")
fmt.Printf("š„ Network Members: 12 (8 active, 4 idle)\n")
fmt.Printf("š Participation Rate: 67% (last 7 days)\n")
fmt.Printf("ā
Consensus Success Rate: 89%\n")
fmt.Printf("āļø Decision Types:\n")
fmt.Printf(" Technical: 45%%, Operational: 30%%\n")
fmt.Printf(" Policy: 20%%, Emergency: 5%%\n")
fmt.Println()
fmt.Println("š Recent Activity:")
fmt.Println(" ⢠DEC-003: Emergency quarantine decision (45m left)")
fmt.Println(" ⢠DEC-002: Task timeout adjustment (6h 30m left)")
fmt.Println(" ⢠DEC-001: libp2p upgrade (2h 15m left)")
fmt.Println(" ⢠DEC-055: Completed - Storage encryption (ā
approved)")
fmt.Println()
}
// announceVoteDecision sends an HMMM message about a vote
func (t *TerminalInterface) announceVoteDecision(decisionID, vote, reasoning string) error {
msgID := t.generateMessageID()
threadID := fmt.Sprintf("decision-%s", decisionID)
message := hmmm.Message{
Topic: fmt.Sprintf("CHORUS/decisions/vote/%s", decisionID),
Type: "decision_vote",
Payload: map[string]interface{}{
"decision_id": decisionID,
"vote": vote,
"reasoning": reasoning,
"voter": t.runtime.Config.Agent.ID,
"voter_type": "human",
},
Version: "1.0",
IssueID: 0,
ThreadID: threadID,
MsgID: msgID,
NodeID: t.runtime.Node.ID().String(),
HopCount: 0,
Timestamp: time.Now().Unix(),
Message: fmt.Sprintf("Vote cast on %s: %s", decisionID, vote),
}
return t.sendHMMMMessage(message)
}
// announceNewDecisionProposal sends an HMMM message about a new decision
func (t *TerminalInterface) announceNewDecisionProposal(decisionID, title, decisionType, rationale string, options []string) error {
msgID := t.generateMessageID()
threadID := fmt.Sprintf("decision-%s", decisionID)
message := hmmm.Message{
Topic: fmt.Sprintf("CHORUS/decisions/proposal/%s", decisionType),
Type: "decision_proposal",
Payload: map[string]interface{}{
"decision_id": decisionID,
"title": title,
"decision_type": decisionType,
"rationale": rationale,
"options": options,
"proposer": t.runtime.Config.Agent.ID,
"proposer_type": "human",
},
Version: "1.0",
IssueID: 0,
ThreadID: threadID,
MsgID: msgID,
NodeID: t.runtime.Node.ID().String(),
HopCount: 0,
Timestamp: time.Now().Unix(),
Message: fmt.Sprintf("New %s decision proposed: %s", decisionType, title),
}
return t.sendHMMMMessage(message)
}
// Patch Management Helper Functions
// showPatchHelp displays detailed patch system information
func (t *TerminalInterface) showPatchHelp() {
fmt.Println("\nš§ CHORUS Patch Management System")
fmt.Println(strings.Repeat("=", 60))
fmt.Println("Create, review, and submit patches for distributed contexts and code changes.")
fmt.Println("Patches enable collaborative editing with temporal navigation and approval workflows.")
fmt.Println()
fmt.Println("Patch Types:")
fmt.Println(" ⢠Context Patches: Changes to UCXL context content")
fmt.Println(" ⢠Code Patches: Traditional diff-based code changes")
fmt.Println(" ⢠Configuration Patches: System and environment changes")
fmt.Println(" ⢠Documentation Patches: Updates to project documentation")
fmt.Println()
fmt.Println("Temporal Navigation:")
fmt.Println(" ~~ - Navigate n decision-hops backward")
fmt.Println(" ^^ - Navigate n decision-hops forward")
fmt.Println(" @