Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion internal/integrations/slack/slack.go
Original file line number Diff line number Diff line change
Expand Up @@ -708,8 +708,9 @@ func renderListItems(api *slack.Client, db *sql.DB, cfg Config, channelID, userI
if item.Category != "" {
category = fmt.Sprintf(" _%s_", item.Category)
}
description := formatItemDescriptionForList(item)
text := fmt.Sprintf("*%s*: %s (%s)%s%s",
item.Author, item.Description, item.Status, source, category)
item.Author, description, item.Status, source, category)
if canManageItem(item, isManager, user) {
editOpt := slack.NewOptionBlockObject(
fmt.Sprintf("edit:%d", item.ID),
Expand Down Expand Up @@ -1337,6 +1338,46 @@ func itemInRange(item WorkItem, from, to time.Time) bool {
return !item.ReportedAt.Before(from) && item.ReportedAt.Before(to)
}

func formatItemDescriptionForList(item WorkItem) string {
description := strings.TrimSpace(item.Description)
tickets := canonicalTicketList(item.TicketIDs)
if tickets == "" {
return description
}
Comment on lines +1341 to +1346
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formatItemDescriptionForList trims item.Description and returns the trimmed value even when there are no ticket IDs (or when the prefix is already present). Previously /list rendered item.Description verbatim, so this subtly changes output formatting and also contradicts the PR note about keeping existing formatting for items without ticket IDs. Consider keeping the original description for the no-ticket / already-prefixed cases (use a trimmed copy only for comparisons), and only trim when you actually need to construct a new prefixed string.

Copilot uses AI. Check for mistakes.
if leading, ok := leadingTicketPrefix(description); ok && canonicalTicketList(leading) == tickets {
return description
}
return fmt.Sprintf("[%s] %s", tickets, description)
}

func leadingTicketPrefix(description string) (string, bool) {
description = strings.TrimSpace(description)
if !strings.HasPrefix(description, "[") {
return "", false
}
end := strings.Index(description, "]")
if end <= 1 {
return "", false
}
return description[1:end], true
}

func canonicalTicketList(ticketIDs string) string {
if strings.TrimSpace(ticketIDs) == "" {
return ""
}
parts := strings.Split(ticketIDs, ",")
cleaned := make([]string, 0, len(parts))
for _, part := range parts {
p := strings.TrimSpace(part)
if p == "" {
continue
}
cleaned = append(cleaned, p)
}
return strings.Join(cleaned, ",")
}

func canManageItem(item WorkItem, isManager bool, user *slack.User) bool {
if isManager {
return true
Expand Down
50 changes: 50 additions & 0 deletions internal/integrations/slack/slack_logic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,56 @@ func TestMapMRStatusAndReportedAt(t *testing.T) {
}
}

func TestFormatItemDescriptionForList(t *testing.T) {
tests := []struct {
name string
item WorkItem
want string
}{
{
name: "prepend single ticket id",
item: WorkItem{
Description: "Tune query timeout for widget pipeline",
TicketIDs: "7003001",
},
want: "[7003001] Tune query timeout for widget pipeline",
},
{
name: "prepend comma list and trim spaces",
item: WorkItem{
Description: "Improve cache warm-up sequence",
TicketIDs: "7003002, 7003003",
},
want: "[7003002,7003003] Improve cache warm-up sequence",
},
{
name: "no duplicate when description already has same prefix",
item: WorkItem{
Description: "[7003004] Add schema validation guard",
TicketIDs: "7003004",
},
want: "[7003004] Add schema validation guard",
},
{
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new tests cover single-ID and single-prefix dedup, but they don't cover the case this code explicitly supports where the existing leading prefix contains multiple IDs and/or spaces (e.g. description starts with "[7003002, 7003003] ..." while TicketIDs is "7003002,7003003"). Adding a test case for that would better pin the intended canonicalization/dedup behavior.

Suggested change
{
{
name: "no duplicate when description has multi-id spaced prefix",
item: WorkItem{
Description: "[7003002, 7003003] Improve cache warm-up sequence",
TicketIDs: "7003002,7003003",
},
want: "[7003002, 7003003] Improve cache warm-up sequence",
},
{

Copilot uses AI. Check for mistakes.
name: "no ticket ids leaves description unchanged",
item: WorkItem{
Description: "Cleanup stale deployment artifacts",
TicketIDs: "",
},
want: "Cleanup stale deployment artifacts",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := formatItemDescriptionForList(tt.item)
if got != tt.want {
t.Fatalf("formatItemDescriptionForList() = %q, want %q", got, tt.want)
}
})
}
}

func TestDeriveBossReportFromTeamReport_FileExists(t *testing.T) {
dir := t.TempDir()
teamName := "TestTeam"
Expand Down