diff --git a/server/src/__tests__/company-portability.test.ts b/server/src/__tests__/company-portability.test.ts index b8bf822d574..b43f7b44829 100644 --- a/server/src/__tests__/company-portability.test.ts +++ b/server/src/__tests__/company-portability.test.ts @@ -2283,6 +2283,72 @@ describe("company portability", () => { expect(materializedFiles["AGENTS.md"]).not.toContain('name: "ClaudeCoder"'); }); + it("preserves issue labelIds through export and import round-trip", async () => { + const portability = companyPortabilityService({} as any); + + projectSvc.list.mockResolvedValue([ + { + id: "project-1", + name: "Launch", + urlKey: "launch", + description: null, + status: "active", + leadAgentId: null, + metadata: null, + defaultProjectWorkspaceId: null, + }, + ]); + projectSvc.listWorkspaces.mockResolvedValue([]); + issueSvc.list.mockResolvedValue([ + { + id: "issue-1", + identifier: "PAP-1", + title: "Labelled task", + description: "Has labels", + projectId: "project-1", + projectWorkspaceId: null, + assigneeAgentId: null, + status: "todo", + priority: "high", + labelIds: ["label-a", "label-b"], + billingCode: null, + executionWorkspaceSettings: null, + assigneeAdapterOverrides: null, + }, + ]); + + const exported = await portability.exportBundle("company-1", { + include: { company: true, agents: false, projects: true, issues: true }, + }); + + const extension = asTextFile(exported.files[".paperclip.yaml"]); + expect(extension).toContain("labelIds:"); + expect(extension).toContain("label-a"); + expect(extension).toContain("label-b"); + + companySvc.create.mockResolvedValue({ id: "company-imported", name: "Imported" }); + accessSvc.ensureMembership.mockResolvedValue(undefined); + agentSvc.list.mockResolvedValue([]); + projectSvc.list.mockResolvedValue([]); + projectSvc.create.mockResolvedValue({ id: "project-imported", name: "Launch", urlKey: "launch" }); + issueSvc.create.mockResolvedValue({ id: "issue-imported", title: "Labelled task" }); + + await portability.importBundle({ + source: { type: "inline", rootPath: exported.rootPath, files: exported.files }, + include: { company: true, agents: false, projects: true, issues: true }, + target: { mode: "new_company", newCompanyName: "Imported" }, + agents: "all", + collisionStrategy: "rename", + }, "user-1"); + + expect(issueSvc.create).toHaveBeenCalledWith( + "company-imported", + expect.objectContaining({ + labelIds: ["label-a", "label-b"], + }), + ); + }); + it("strips root AGENTS frontmatter when importing a nested agent entry path", async () => { const portability = companyPortabilityService({} as any); diff --git a/server/src/routes/issues.ts b/server/src/routes/issues.ts index a3da3cec97c..767046dd720 100644 --- a/server/src/routes/issues.ts +++ b/server/src/routes/issues.ts @@ -1739,6 +1739,10 @@ export function issueRoutes( existing.status === "backlog" && issue.status !== "backlog" && req.body.status !== undefined; + const statusChangedFromBlockedToTodo = + existing.status === "blocked" && + issue.status === "todo" && + req.body.status !== undefined; const previousExecutionState = parseIssueExecutionState(existing.executionState); const nextExecutionState = parseIssueExecutionState(issue.executionState); const executionStageWakeup = buildExecutionStageWakeup({ @@ -1792,7 +1796,7 @@ export function issueRoutes( }); } - if (!assigneeChanged && statusChangedFromBacklog && issue.assigneeAgentId) { + if (!assigneeChanged && (statusChangedFromBacklog || statusChangedFromBlockedToTodo) && issue.assigneeAgentId) { addWakeup(issue.assigneeAgentId, { source: "automation", triggerDetail: "system", diff --git a/server/src/services/company-portability.ts b/server/src/services/company-portability.ts index 9dc3262fb4e..ff29a180b2d 100644 --- a/server/src/services/company-portability.ts +++ b/server/src/services/company-portability.ts @@ -4388,7 +4388,7 @@ export function companyPortabilityService(db: Db, storage?: StorageService) { billingCode: manifestIssue.billingCode, assigneeAdapterOverrides: manifestIssue.assigneeAdapterOverrides, executionWorkspaceSettings: manifestIssue.executionWorkspaceSettings, - labelIds: [], + labelIds: manifestIssue.labelIds ?? [], }); } }