feat: move unfinished tickets between releases

- Bulk editing gets «Release…» (open releases or none), and the list
  view a release filter, also reachable from each release («Ver en la
  lista», ?release=).
- Archiving a release asks where its unfinished tickets go, as closing
  a sprint does: ReleaseArchivedEvent carries `moveTo` (an open release
  of the same project, or none) and the saga moves them there; finished
  ones stay. In GraphQL, REST and the MCP's archive_release.
- Chapter 10 lists the next features and the ideas to weigh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-14 21:55:45 +02:00
parent 0a73eda9b2
commit 993f80b4b9
34 changed files with 408 additions and 48 deletions

View File

@@ -96,6 +96,7 @@ export interface IssueListFilter {
priorities?: IssuePriority[];
assigneeId?: string;
unassigned?: boolean;
releaseId?: string;
limit: number;
}
@@ -134,6 +135,8 @@ export interface BulkChange {
assigneeId?: string | null;
/** null: back to the backlog. */
sprintId?: string | null;
/** null: out of its release. */
releaseId?: string | null;
priority?: IssuePriority;
addLabels?: string[];
}

View File

@@ -289,7 +289,11 @@ export abstract class ReleasesGateway {
releaseId: string,
force: boolean,
): Observable<CommandResult>;
abstract archive(releaseId: string): Observable<CommandResult>;
/** Its unfinished tickets go to `moveTo` (an open release) or leave it. */
abstract archive(
releaseId: string,
moveTo?: string | null,
): Observable<CommandResult>;
abstract burnup(releaseId: string): Observable<ReleaseBurnup>;
/** A Markdown draft from the release's finished tickets (not saved). */
abstract notesDraft(releaseId: string): Observable<string>;