diff --git a/web/src/components/teams/TeamRequirementCard.tsx b/web/src/components/teams/TeamRequirementCard.tsx index f35bca8e..c1648882 100644 --- a/web/src/components/teams/TeamRequirementCard.tsx +++ b/web/src/components/teams/TeamRequirementCard.tsx @@ -39,15 +39,21 @@ export function TeamRequirementCard(props: { const [expanded, setExpanded] = useState(hasPendingDecision) const [showAll, setShowAll] = useState(false) - const milestones = useMemo(() => selectMilestones(messages), [messages]) - const hiddenCount = messages.length - milestones.length + // The opening human message IS the ask shown at the top; hide it here so the + // same sentence is not repeated inside the process. + const openingAskSeq = requirement ? (messages.find((message) => message.fromKind === 'human')?.seq ?? null) : null + const timelineMessages = openingAskSeq === null + ? messages + : messages.filter((message) => message.seq !== openingAskSeq) + const milestones = useMemo(() => selectMilestones(timelineMessages), [timelineMessages]) + const hiddenCount = timelineMessages.length - milestones.length const outcome = requirementOutcome(requirement, tasks, messages) const askText = requirement?.body?.trim() || requirement?.title || null const title = requirement ? requirement.title : t('team.requirement.other') const assignees = Array.from(new Set(tasks .map((task) => props.members.find((member) => member.sessionId === task.assigneeSessionId)?.role) .filter((role): role is string => Boolean(role)))) - const shown = showAll ? messages : milestones + const shown = showAll ? timelineMessages : milestones return (