feat: ask a teammate to review a ticket

«Pedir revisión» on a ticket asks a member (with an optional note): they
are notified and see it under «Te piden revisión» in my work until they
answer «Todo bien» or «Pedir cambios» (with what to change) from the
ticket's Revisiones box; whoever asked hears the answer and can withdraw
an open request. Events of the ticket (requested, answered, cancelled),
so they show in its history and the activity feed. Viewers can be asked
and answer; not oneself, nor twice the same person with one pending.

API: requestReview / answerReview / cancelReview, Issue.reviews,
myIssues(reviewing); POST /api/issues/{issue}/reviews,
POST …/reviews/{id}/answer, DELETE …/reviews/{id}. MCP: request_review,
answer_review, my_issues reviewing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-20 20:38:30 +02:00
parent 172c53d21d
commit 93d028e870
53 changed files with 2836 additions and 54 deletions

View File

@@ -1,3 +1,4 @@
import { ReviewVerdict } from '../issue/review';
import { DevLink } from '../issue/dev-link';
import { IssueLinkType, IssuePriority } from '../issue/issue.enums';
import { StatusCategory } from '../project/project-settings';
@@ -85,6 +86,8 @@ export class IssueReadModel {
attachments!: AttachmentReadModel[];
/** People following the ticket. */
watchers!: UserRefReadModel[];
/** Asked reviews, open and answered, oldest first. */
reviews!: IssueReviewReadModel[];
/** How many want it done. */
votes!: number;
/** Who voted: to tell someone whether they did; never shown as a list. */
@@ -103,3 +106,16 @@ export class IssueReadModel {
/** Position of the last projected event. */
version!: number;
}
/** A review asked on a ticket, as the read side shows it. */
export class IssueReviewReadModel {
id!: string;
requester!: UserRefReadModel;
reviewer!: UserRefReadModel;
note!: string | null;
requestedAt!: string;
/** Null while waiting for an answer. */
verdict!: ReviewVerdict | null;
answer!: string | null;
answeredAt!: string | null;
}