feat(goals): show assignee for each bead in gt goals output

Add assignee display to both list and single-goal views. In list view,
assignee appears on the second line when present. In single-goal view,
it appears as a dedicated field after priority. JSON output also includes
the assignee field.

Closes: gt-libj

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
furiosa
2026-01-23 15:47:18 -08:00
committed by John Ogle
parent d12408703b
commit beb863897f

View File

@@ -75,6 +75,7 @@ type goalInfo struct {
Title string `json:"title"` Title string `json:"title"`
Status string `json:"status"` Status string `json:"status"`
Priority int `json:"priority"` Priority int `json:"priority"`
Assignee string `json:"assignee,omitempty"`
ConvoyCount int `json:"convoy_count"` ConvoyCount int `json:"convoy_count"`
LastMovement time.Time `json:"last_movement,omitempty"` LastMovement time.Time `json:"last_movement,omitempty"`
StalenessHrs float64 `json:"staleness_hours"` StalenessHrs float64 `json:"staleness_hours"`
@@ -99,6 +100,7 @@ func showGoal(goalID string) error {
Status string `json:"status"` Status string `json:"status"`
Priority int `json:"priority"` Priority int `json:"priority"`
IssueType string `json:"issue_type"` IssueType string `json:"issue_type"`
Assignee string `json:"assignee"`
CreatedAt string `json:"created_at"` CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"` UpdatedAt string `json:"updated_at"`
} }
@@ -131,6 +133,7 @@ func showGoal(goalID string) error {
Title: goal.Title, Title: goal.Title,
Status: goal.Status, Status: goal.Status,
Priority: goal.Priority, Priority: goal.Priority,
Assignee: goal.Assignee,
ConvoyCount: len(convoys), ConvoyCount: len(convoys),
LastMovement: lastMovement, LastMovement: lastMovement,
StalenessHrs: stalenessHrs, StalenessHrs: stalenessHrs,
@@ -145,6 +148,9 @@ func showGoal(goalID string) error {
fmt.Printf("%s P%d %s: %s\n\n", icon, goal.Priority, style.Bold.Render(goal.ID), goal.Title) fmt.Printf("%s P%d %s: %s\n\n", icon, goal.Priority, style.Bold.Render(goal.ID), goal.Title)
fmt.Printf(" Status: %s\n", goal.Status) fmt.Printf(" Status: %s\n", goal.Status)
fmt.Printf(" Priority: P%d\n", goal.Priority) fmt.Printf(" Priority: P%d\n", goal.Priority)
if goal.Assignee != "" {
fmt.Printf(" Assignee: @%s\n", goal.Assignee)
}
fmt.Printf(" Convoys: %d\n", len(convoys)) fmt.Printf(" Convoys: %d\n", len(convoys))
fmt.Printf(" Last activity: %s\n", formatLastActivity(lastMovement)) fmt.Printf(" Last activity: %s\n", formatLastActivity(lastMovement))
@@ -222,6 +228,7 @@ func listGoals() error {
Title: epic.Title, Title: epic.Title,
Status: epic.Status, Status: epic.Status,
Priority: epic.Priority, Priority: epic.Priority,
Assignee: epic.Assignee,
ConvoyCount: len(convoys), ConvoyCount: len(convoys),
LastMovement: lastMovement, LastMovement: lastMovement,
StalenessHrs: stalenessHrs, StalenessHrs: stalenessHrs,
@@ -264,9 +271,13 @@ func listGoals() error {
fmt.Printf(" %s %s %s: %s\n", g.StalenessIcon, priorityStr, g.ID, g.Title) fmt.Printf(" %s %s %s: %s\n", g.StalenessIcon, priorityStr, g.ID, g.Title)
// Second line with convoy count and staleness // Second line with convoy count, staleness, and assignee (if any)
activityStr := formatActivityShort(g.StalenessHrs) activityStr := formatActivityShort(g.StalenessHrs)
fmt.Printf(" %d convoy(s) | %s\n\n", g.ConvoyCount, activityStr) if g.Assignee != "" {
fmt.Printf(" %d convoy(s) | %s | @%s\n\n", g.ConvoyCount, activityStr, g.Assignee)
} else {
fmt.Printf(" %d convoy(s) | %s\n\n", g.ConvoyCount, activityStr)
}
} }
return nil return nil
@@ -458,6 +469,7 @@ type epicRecord struct {
Status string `json:"status"` Status string `json:"status"`
Priority int `json:"priority"` Priority int `json:"priority"`
UpdatedAt string `json:"updated_at"` UpdatedAt string `json:"updated_at"`
Assignee string `json:"assignee"`
} }
// collectEpicsFromAllRigs queries all rigs for epics and aggregates them. // collectEpicsFromAllRigs queries all rigs for epics and aggregates them.