From 6e73fb6e8d07f89d6bcea4d2db05a616afbf322a Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 18:23:35 +0000 Subject: [PATCH] fix(agentic): preserve issue labels on unlock --- pkg/mcp/agentic/issue.go | 26 +++++++++++++++++++++----- pkg/mcp/agentic/issue_test.go | 6 ++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/pkg/mcp/agentic/issue.go b/pkg/mcp/agentic/issue.go index 7ad750b..4d3c029 100644 --- a/pkg/mcp/agentic/issue.go +++ b/pkg/mcp/agentic/issue.go @@ -31,9 +31,12 @@ type IssueDispatchInput struct { } type forgeIssue struct { - Title string `json:"title"` - Body string `json:"body"` - State string `json:"state"` + Title string `json:"title"` + Body string `json:"body"` + State string `json:"state"` + Labels []struct { + Name string `json:"name"` + } `json:"labels"` Assignee *struct { Login string `json:"login"` } `json:"assignee"` @@ -88,7 +91,7 @@ func (s *PrepSubsystem) dispatchIssue(ctx context.Context, req *mcp.CallToolRequ var dispatchErr error defer func() { if dispatchErr != nil { - _ = s.unlockIssue(ctx, input.Org, input.Repo, input.Issue) + _ = s.unlockIssue(ctx, input.Org, input.Repo, input.Issue, issue.Labels) } }() @@ -118,10 +121,23 @@ func (s *PrepSubsystem) dispatchIssue(ctx context.Context, req *mcp.CallToolRequ }) } -func (s *PrepSubsystem) unlockIssue(ctx context.Context, org, repo string, issue int) error { +func (s *PrepSubsystem) unlockIssue(ctx context.Context, org, repo string, issue int, labels []struct { + Name string `json:"name"` +}) error { updateURL := fmt.Sprintf("%s/api/v1/repos/%s/%s/issues/%d", s.forgeURL, org, repo, issue) + issueLabels := make([]string, 0, len(labels)) + for _, label := range labels { + if label.Name == "in-progress" { + continue + } + issueLabels = append(issueLabels, label.Name) + } + if issueLabels == nil { + issueLabels = []string{} + } payload, err := json.Marshal(map[string]any{ "assignees": []string{}, + "labels": issueLabels, }) if err != nil { return coreerr.E("unlockIssue", "failed to encode issue unlock", err) diff --git a/pkg/mcp/agentic/issue_test.go b/pkg/mcp/agentic/issue_test.go index 8eb74c6..f5776bd 100644 --- a/pkg/mcp/agentic/issue_test.go +++ b/pkg/mcp/agentic/issue_test.go @@ -105,6 +105,9 @@ func TestDispatchIssue_Good_UnlocksOnPrepFailure(t *testing.T) { "title": "Fix login crash", "body": "details", "state": "open", + "labels": []map[string]any{ + {"name": "bug"}, + }, }) case http.MethodPatch: w.WriteHeader(http.StatusOK) @@ -148,6 +151,9 @@ func TestDispatchIssue_Good_UnlocksOnPrepFailure(t *testing.T) { if !strings.Contains(bodies[2], `"assignees":[]`) { t.Fatalf("expected unlock request to clear assignees, got %s", bodies[2]) } + if !strings.Contains(bodies[2], `"labels":["bug"]`) { + t.Fatalf("expected unlock request to preserve original labels, got %s", bodies[2]) + } } func TestLockIssue_Good_RequestBody(t *testing.T) {