diff --git a/apps/portal/src/components/ShortId.stories.tsx b/apps/portal/src/components/ShortId.stories.tsx index 55d0563c0..6e7e7e1f3 100644 --- a/apps/portal/src/components/ShortId.stories.tsx +++ b/apps/portal/src/components/ShortId.stories.tsx @@ -44,3 +44,13 @@ export const HoverRevealsFullIdAndCopy: Story = { await expect(screen.getAllByText(FULL_ID).length).toBeGreaterThan(0); }, }; + +/** The run detail metadata labels its parent submission ID explicitly. */ +export const SubmissionId: Story = { + args: { label: "submission ID" }, + play: async ({ canvas }) => { + await userEvent.hover(canvas.getByText("abcdef12")); + const [button] = await screen.findAllByRole("button", { name: "Copy submission ID" }); + await expect(button).toBeVisible(); + }, +}; diff --git a/apps/portal/src/pages/RunDetail.tsx b/apps/portal/src/pages/RunDetail.tsx index 77ac6b0fa..b0e28c955 100644 --- a/apps/portal/src/pages/RunDetail.tsx +++ b/apps/portal/src/pages/RunDetail.tsx @@ -31,6 +31,7 @@ import { ReportThumbnail } from "@/components/ReportThumbnail"; import { CriteriaBadge } from "@/components/CriteriaBadge"; import { TaskPromptBadge } from "@/components/TaskPromptBadge"; import { AgentBadge } from "@/components/AgentBadge"; +import { ShortId } from "@/components/ShortId"; import { SkillRevisionLinks } from "@/components/SkillRevisionLinks"; import { AlertTriangle, ArrowLeft, Copy, Check, Sparkles, CheckCircle2, XCircle, MinusCircle, FileText, Plus, Download, Loader2, Archive, Video, LayoutGrid, List, Puzzle, RotateCcw, ChevronDown, Clock, Pause, Play, ArrowUpDown, X, Boxes } from "lucide-react"; import { formatDate, formatId, formatDuration, cn } from "@/lib/utils"; @@ -674,6 +675,12 @@ export function RunDetail() { {/* Tier 2 — labeled configuration + metrics */}
+ {run.submissionId && ( + } + /> + )} } diff --git a/docs/architecture/app-design.md b/docs/architecture/app-design.md index f1a243262..bcafbdb30 100644 --- a/docs/architecture/app-design.md +++ b/docs/architecture/app-design.md @@ -678,7 +678,8 @@ Both follow the same rules: A sibling affordance, `components/ShortId.tsx`, applies the same hoverable-tooltip pattern to **identifiers**: the Runs list renders run and submission IDs truncated to 8 chars -(`formatId`), and on hover the tooltip reveals the full ID plus a copy-to-clipboard button. The +(`formatId`), and Run detail shows the parent submission ID in its metadata. On +hover the tooltip reveals the full ID plus a copy-to-clipboard button. The trigger stays an inline `` (not a link) so the row click still navigates to the run; the copy button calls `e.stopPropagation()` so copying never triggers row navigation.