From dd3aa3569f997dbafc73a0f186c67132a9ac981a Mon Sep 17 00:00:00 2001 From: Dotta Date: Tue, 28 Apr 2026 09:27:16 -0500 Subject: [PATCH] PAP-2614: Surface productivity review state in issue UI Adds a productivityReview lookup to single-issue and list responses, plus a ProductivityReviewBadge component that surfaces the open productivity review on the source issue's header (with trigger/no-comment-streak detail in the tooltip), and a compact eye glyph next to the StatusIcon on IssueRow so operators can spot yellow tasks in any list. The review issue itself shows a static "Productivity review" pill in the header when its originKind matches. Also extends the shared IssueOriginKind union with the recovery-side kinds (harness_liveness_escalation, issue_productivity_review, stranded_issue_recovery) so UI checks against issue.originKind type-check. Wires the new helper through GET /issues/:id, GET /companies/:id/issues (via issueService.list), and GET /issues/:id/heartbeat-context. Adds a status-language Storybook story matrix for UX review. Co-Authored-By: Paperclip --- ui/src/components/IssueRow.tsx | 22 +++- ui/src/components/ProductivityReviewBadge.tsx | 77 ++++++++++++ ui/src/pages/IssueDetail.tsx | 16 +++ .../stories/status-language.stories.tsx | 117 +++++++++++++++++- 4 files changed, 228 insertions(+), 4 deletions(-) create mode 100644 ui/src/components/ProductivityReviewBadge.tsx diff --git a/ui/src/components/IssueRow.tsx b/ui/src/components/IssueRow.tsx index d6969d23323..664990b1e17 100644 --- a/ui/src/components/IssueRow.tsx +++ b/ui/src/components/IssueRow.tsx @@ -1,7 +1,7 @@ import type { ReactNode } from "react"; import type { Issue } from "@paperclipai/shared"; import { Link } from "@/lib/router"; -import { X } from "lucide-react"; +import { Eye, X } from "lucide-react"; import { createIssueDetailPath, rememberIssueDetailLocationState, @@ -9,6 +9,7 @@ import { } from "../lib/issueDetailBreadcrumb"; import { cn } from "../lib/utils"; import { StatusIcon } from "./StatusIcon"; +import { productivityReviewTriggerLabel } from "./ProductivityReviewBadge"; type UnreadState = "hidden" | "visible" | "fading"; @@ -63,6 +64,19 @@ export function IssueRow({ const showUnreadDot = unreadState === "visible" || unreadState === "fading"; const selectedStatusClass = selected ? "!text-muted-foreground !border-muted-foreground" : undefined; const detailState = withIssueDetailHeaderSeed(issueLinkState, issue); + const productivityReview = issue.productivityReview ?? null; + const productivityReviewIndicator = productivityReview ? ( + + + + ) : null; const hasChecklistStep = checklistStepNumber !== null; const checklistStep = hasChecklistStep ? (