feat: add overseer experience commands (gt focus, gt attention)
Some checks failed
CI / Check for .beads changes (push) Has been skipped
CI / Check embedded formulas (push) Failing after 15s
CI / Test (push) Failing after 1m29s
CI / Lint (push) Failing after 19s
CI / Integration Tests (push) Successful in 1m14s
CI / Coverage Report (push) Has been skipped
Windows CI / Windows Build and Unit Tests (push) Has been cancelled
Some checks failed
CI / Check for .beads changes (push) Has been skipped
CI / Check embedded formulas (push) Failing after 15s
CI / Test (push) Failing after 1m29s
CI / Lint (push) Failing after 19s
CI / Integration Tests (push) Successful in 1m14s
CI / Coverage Report (push) Has been skipped
Windows CI / Windows Build and Unit Tests (push) Has been cancelled
Implements the Overseer Experience epic (gt-k0kn): - gt focus: Shows stalest high-priority goals, sorted by priority × staleness - gt attention: Shows blocked items, PRs awaiting review, stuck workers - gt status: Now includes GOALS and ATTENTION summary sections - gt convoy list: Added --orphans, --epic, --by-epic flags These commands reduce Mayor bottleneck by giving the overseer direct visibility into system state without needing to ask Mayor. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
@@ -439,6 +440,55 @@ func outputStatusText(status TownStatus) error {
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// Goals summary (top 3 stalest high-priority)
|
||||
goals, _ := collectFocusItems(status.Location)
|
||||
// Sort by score (highest first)
|
||||
sort.Slice(goals, func(i, j int) bool {
|
||||
return goals[i].Score > goals[j].Score
|
||||
})
|
||||
if len(goals) > 0 {
|
||||
fmt.Printf("%s (%d active)\n", style.Bold.Render("GOALS"), len(goals))
|
||||
// Show top 3
|
||||
showCount := 3
|
||||
if len(goals) < showCount {
|
||||
showCount = len(goals)
|
||||
}
|
||||
for i := 0; i < showCount; i++ {
|
||||
g := goals[i]
|
||||
var indicator string
|
||||
switch g.Staleness {
|
||||
case "stuck":
|
||||
indicator = style.Error.Render("🔴")
|
||||
case "stale":
|
||||
indicator = style.Warning.Render("🟡")
|
||||
default:
|
||||
indicator = style.Success.Render("🟢")
|
||||
}
|
||||
fmt.Printf(" %s P%d %s: %s\n", indicator, g.Priority, g.ID, truncateWithEllipsis(g.Title, 40))
|
||||
}
|
||||
if len(goals) > showCount {
|
||||
fmt.Printf(" %s\n", style.Dim.Render(fmt.Sprintf("... and %d more (gt focus)", len(goals)-showCount)))
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// Attention summary (blocked items, reviews)
|
||||
attention := collectAttentionSummary(status.Location)
|
||||
if attention.Total > 0 {
|
||||
fmt.Printf("%s (%d items)\n", style.Bold.Render("ATTENTION"), attention.Total)
|
||||
if attention.Blocked > 0 {
|
||||
fmt.Printf(" • %d blocked issue(s)\n", attention.Blocked)
|
||||
}
|
||||
if attention.Reviews > 0 {
|
||||
fmt.Printf(" • %d PR(s) awaiting review\n", attention.Reviews)
|
||||
}
|
||||
if attention.Stuck > 0 {
|
||||
fmt.Printf(" • %d stuck worker(s)\n", attention.Stuck)
|
||||
}
|
||||
fmt.Printf(" %s\n", style.Dim.Render("→ gt attention for details"))
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// Role icons - uses centralized emojis from constants package
|
||||
roleIcons := map[string]string{
|
||||
constants.RoleMayor: constants.EmojiMayor,
|
||||
@@ -1232,3 +1282,36 @@ func getAgentHook(b *beads.Beads, role, agentAddress, roleType string) AgentHook
|
||||
|
||||
return hook
|
||||
}
|
||||
|
||||
// AttentionSummary holds counts of items needing attention for status display.
|
||||
type AttentionSummary struct {
|
||||
Blocked int
|
||||
Reviews int
|
||||
Stuck int
|
||||
Decisions int
|
||||
Total int
|
||||
}
|
||||
|
||||
// collectAttentionSummary gathers counts of items needing attention.
|
||||
func collectAttentionSummary(townRoot string) AttentionSummary {
|
||||
summary := AttentionSummary{}
|
||||
|
||||
// Count blocked items (reuse logic from attention.go)
|
||||
blocked := collectBlockedItems(townRoot)
|
||||
summary.Blocked = len(blocked)
|
||||
|
||||
// Count reviews
|
||||
reviews := collectReviewItems(townRoot)
|
||||
summary.Reviews = len(reviews)
|
||||
|
||||
// Count stuck workers
|
||||
stuck := collectStuckWorkers(townRoot)
|
||||
summary.Stuck = len(stuck)
|
||||
|
||||
// Count decisions
|
||||
decisions := collectDecisionItems(townRoot)
|
||||
summary.Decisions = len(decisions)
|
||||
|
||||
summary.Total = summary.Blocked + summary.Reviews + summary.Stuck + summary.Decisions
|
||||
return summary
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user