feat: teams within a project

Projects keep teams of members in their settings (settings.teams; people
outside the project are dropped, teams are archived, not removed; absent
when saving means unchanged). Tickets go to a team (`team`, also filtered
in the list and in MCP search_issues), and a comment mentioning
@[Frontend](team-FRONT) tells each of its members. Settings has the teams
with their members, the ticket a «Equipo» select, the list a team filter,
and «@» offers the teams after the people.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-15 16:20:35 +02:00
parent 4acf629106
commit 869acd3f1f
41 changed files with 895 additions and 13 deletions

View File

@@ -339,6 +339,9 @@ input CreateIssueInput {
"""When work should start (roadmap), YYYY-MM-DD"""
startDate: String
storyPoints: Int
"""A team id"""
team: String
title: String!
"""A ticket type id"""
@@ -607,6 +610,9 @@ type Issue {
status: String!
statusCategory: StatusCategory!
storyPoints: Int
"""A team id"""
team: String
title: String!
"""In the trash since then; null when it is not"""
@@ -669,6 +675,9 @@ input IssueFilterInput {
sort: IssueSort = RECENT
sprintId: ID
statuses: [String!]
"""Team ids"""
teams: [String!]
types: [String!]
unassigned: Boolean
@@ -1204,6 +1213,7 @@ type ProjectSettings {
customFields: [CustomFieldDefinition!]!
issueTypes: [IssueTypeOption!]!
statuses: [WorkflowStatus!]!
teams: [Team!]!
transitions: [StatusTransitions!]!
}
@@ -1222,6 +1232,9 @@ input ProjectSettingsInput {
customFields: [CustomFieldDefinitionInput!]
issueTypes: [IssueTypeOptionInput!]!
statuses: [WorkflowStatusInput!]!
"""Absent: unchanged. Teams cannot be removed: archive them."""
teams: [TeamInput!]
transitions: [StatusTransitionsInput!]!
}
@@ -1654,6 +1667,21 @@ type Subscription {
sprintChanged(projectId: ID!): SprintChange!
}
"""A group of members: tickets go to it; @team mentions tell them all"""
type Team {
archived: Boolean!
id: String!
memberIds: [ID!]!
name: String!
}
input TeamInput {
archived: Boolean! = false
id: String!
memberIds: [ID!]! = []
name: String!
}
type TeamLoad {
blocked: Int!
openPoints: Int!
@@ -1696,6 +1724,9 @@ input UpdateIssueInput {
"""When work should start (roadmap), YYYY-MM-DD"""
startDate: String
storyPoints: Int
"""A team id"""
team: String
title: String
type: String
}