diff --git a/apps/code/src/renderer/features/inbox/components/InboxSignalsTab.tsx b/apps/code/src/renderer/features/inbox/components/InboxSignalsTab.tsx
index 0a64f6387..e1f8b2a16 100644
--- a/apps/code/src/renderer/features/inbox/components/InboxSignalsTab.tsx
+++ b/apps/code/src/renderer/features/inbox/components/InboxSignalsTab.tsx
@@ -33,9 +33,6 @@ import {
} from "@features/inbox/utils/filterReports";
import { INBOX_REFETCH_INTERVAL_MS } from "@features/inbox/utils/inboxConstants";
import { setPendingInboxOpenMethod } from "@features/inbox/utils/pendingInboxOpenMethod";
-import { DiscoveredTaskDetailPane } from "@features/setup/components/DiscoveredTaskDetailPane";
-import { RecommendedSetupTasks } from "@features/setup/components/RecommendedSetupTasks";
-import { useSetupStore } from "@features/setup/stores/setupStore";
import {
useIntegrations,
useRepositoryIntegration,
@@ -350,9 +347,6 @@ export function InboxSignalsTab() {
// ── Click handler: plain / cmd / shift ──────────────────────────────────
const handleReportClick = useCallback(
(reportId: string, event: { metaKey: boolean; shiftKey: boolean }) => {
- // Selecting a real report clears any discovered-task selection so the
- // detail pane can swap to the report.
- useSetupStore.getState().selectDiscoveredTask(null);
if (event.shiftKey) {
setPendingInboxOpenMethod("click_shift");
selectRange(
@@ -433,28 +427,6 @@ export function InboxSignalsTab() {
};
}, [sidebarIsResizing, setSidebarWidth, setSidebarIsResizing]);
- // ── Discovered-task suggestions (rendered inline at top of list) ───────
- const discoveredTasks = useSetupStore((s) => s.discoveredTasks);
- const hasDiscoveredTasks = discoveredTasks.length > 0;
- const selectedDiscoveredTaskId = useSetupStore(
- (s) => s.selectedDiscoveredTaskId,
- );
- const selectDiscoveredTask = useSetupStore((s) => s.selectDiscoveredTask);
- const selectedDiscoveredTask =
- discoveredTasks.find((t) => t.id === selectedDiscoveredTaskId) ?? null;
-
- const handleSelectDiscoveredTask = useCallback(
- (taskId: string) => {
- selectDiscoveredTask(taskId);
- clearSelection();
- },
- [selectDiscoveredTask, clearSelection],
- );
-
- const handleCloseDiscoveredTaskPane = useCallback(() => {
- selectDiscoveredTask(null);
- }, [selectDiscoveredTask]);
-
// ── Layout mode (computed early — needed by focus effect below) ────────
const hasReports = allReports.length > 0;
const hasActiveFilters =
@@ -462,10 +434,7 @@ export function InboxSignalsTab() {
suggestedReviewerFilter.length > 0 ||
statusFilter.length < 5;
const shouldShowTwoPane =
- hasReports ||
- !!searchQuery.trim() ||
- hasActiveFilters ||
- hasDiscoveredTasks;
+ hasReports || !!searchQuery.trim() || hasActiveFilters;
// Sticky: once we enter two-pane mode, stay there even if a refetch
// momentarily empties the list (e.g. when sort order changes).
@@ -704,9 +673,6 @@ export function InboxSignalsTab() {
onReportAction={tracker.signalAction}
/>
-
- ) : selectedDiscoveredTask ? (
-
) : (
)}
diff --git a/apps/code/src/renderer/features/setup/components/DiscoveredTaskDetailPane.tsx b/apps/code/src/renderer/features/setup/components/DiscoveredTaskDetailDialog.tsx
similarity index 68%
rename from apps/code/src/renderer/features/setup/components/DiscoveredTaskDetailPane.tsx
rename to apps/code/src/renderer/features/setup/components/DiscoveredTaskDetailDialog.tsx
index cc3cdbf6d..ac94649dd 100644
--- a/apps/code/src/renderer/features/setup/components/DiscoveredTaskDetailPane.tsx
+++ b/apps/code/src/renderer/features/setup/components/DiscoveredTaskDetailDialog.tsx
@@ -1,4 +1,5 @@
import { Badge } from "@components/ui/Badge";
+import { Button } from "@components/ui/Button";
import { MarkdownRenderer } from "@features/editor/components/MarkdownRenderer";
import { useFolders } from "@features/folders/hooks/useFolders";
import { useSetupStore } from "@features/setup/stores/setupStore";
@@ -9,22 +10,53 @@ import {
FALLBACK_CATEGORY_CONFIG,
} from "@features/setup/utils/categoryConfig";
import { useDetectedCloudRepository } from "@hooks/useDetectedCloudRepository";
-import { PlusIcon, SparkleIcon, X as XIcon } from "@phosphor-icons/react";
-import { Box, Button, Flex, ScrollArea, Text } from "@radix-ui/themes";
+import { PlusIcon, SparkleIcon } from "@phosphor-icons/react";
+import {
+ Box,
+ Dialog,
+ Flex,
+ ScrollArea,
+ Text,
+ VisuallyHidden,
+} from "@radix-ui/themes";
import { ANALYTICS_EVENTS } from "@shared/types/analytics";
import { useActiveRepoStore } from "@stores/activeRepoStore";
import { useNavigationStore } from "@stores/navigationStore";
import { track } from "@utils/analytics";
-interface DiscoveredTaskDetailPaneProps {
- task: DiscoveredTask;
+interface DiscoveredTaskDetailDialogProps {
+ task: DiscoveredTask | null;
onClose: () => void;
}
-export function DiscoveredTaskDetailPane({
+export function DiscoveredTaskDetailDialog({
+ task,
+ onClose,
+}: DiscoveredTaskDetailDialogProps) {
+ return (
+ {
+ if (!open) onClose();
+ }}
+ >
+
+
+ {task?.title ?? "Suggestion"}
+
+ {task && }
+
+
+ );
+}
+
+function DialogBody({
task,
onClose,
-}: DiscoveredTaskDetailPaneProps) {
+}: {
+ task: DiscoveredTask;
+ onClose: () => void;
+}) {
const config = CATEGORY_CONFIG[task.category] ?? FALLBACK_CATEGORY_CONFIG;
const CategoryIcon = config.icon;
@@ -48,6 +80,7 @@ export function DiscoveredTaskDetailPane({
useSetupStore
.getState()
.removeDiscoveredTask(task.id, task.repoPath ?? null);
+ onClose();
navigateToTaskInput({
initialPrompt,
folderId,
@@ -66,47 +99,30 @@ export function DiscoveredTaskDetailPane({
useSetupStore
.getState()
.removeDiscoveredTask(task.id, task.repoPath ?? null);
+ onClose();
};
return (
- <>
-
-
-
-
- Suggested
-
-
- {task.title}
-
-
-
-
-
+
+
+
+
+ Suggested
+
+
+ {task.title}
+
-
-
+
+
@@ -162,32 +178,16 @@ export function DiscoveredTaskDetailPane({
-
-
);
}
diff --git a/apps/code/src/renderer/features/setup/components/RecommendedSetupTasks.tsx b/apps/code/src/renderer/features/setup/components/RecommendedSetupTasks.tsx
deleted file mode 100644
index 3e0d19c53..000000000
--- a/apps/code/src/renderer/features/setup/components/RecommendedSetupTasks.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import { Badge } from "@components/ui/Badge";
-import { ReportListRow } from "@features/inbox/components/list/ReportListRow";
-import { useSetupStore } from "@features/setup/stores/setupStore";
-import { discoveredTaskToSignalReport } from "@features/setup/utils/discoveredTaskToSignalReport";
-import { SparkleIcon } from "@phosphor-icons/react";
-import { Flex, Text, Tooltip } from "@radix-ui/themes";
-import { useMemo } from "react";
-
-interface RecommendedSetupTasksProps {
- onSelectTask: (taskId: string) => void;
-}
-
-export function RecommendedSetupTasks({
- onSelectTask,
-}: RecommendedSetupTasksProps) {
- const tasks = useSetupStore((s) => s.discoveredTasks);
- const anyDiscoveryRunning = useSetupStore((s) =>
- Object.values(s.discoveryByRepo).some((d) => d.status === "running"),
- );
- const selectedDiscoveredTaskId = useSetupStore(
- (s) => s.selectedDiscoveredTaskId,
- );
-
- const fakeReports = useMemo(
- () => tasks.map(discoveredTaskToSignalReport),
- [tasks],
- );
-
- if (tasks.length === 0) return null;
-
- return (
-
- {anyDiscoveryRunning && (
-
-
- scanning for more…
-
-
- )}
- {fakeReports.map((report, index) => (
- onSelectTask(report.id)}
- onToggleChecked={() => {}}
- iconOverride={
-
-
-
-
-
- }
- prependBadges={
-
-
- Suggested
-
- }
- />
- ))}
-
- );
-}
diff --git a/apps/code/src/renderer/features/setup/stores/setupStore.ts b/apps/code/src/renderer/features/setup/stores/setupStore.ts
index 964ae1b7f..6a6ca14b1 100644
--- a/apps/code/src/renderer/features/setup/stores/setupStore.ts
+++ b/apps/code/src/renderer/features/setup/stores/setupStore.ts
@@ -54,7 +54,6 @@ interface SetupStoreState {
discoveredTasks: DiscoveredTask[];
discoveryByRepo: Record;
enricherByRepo: Record;
- selectedDiscoveredTaskId: string | null;
}
interface SetupStoreActions {
@@ -66,7 +65,6 @@ interface SetupStoreActions {
completeEnrichment: (repoPath: string) => void;
failEnrichment: (repoPath: string) => void;
removeDiscoveredTask: (taskId: string, repoPath: string | null) => void;
- selectDiscoveredTask: (taskId: string | null) => void;
addEnricherSuggestionIfMissing: (task: DiscoveredTask) => void;
pushDiscoveryActivity: (repoPath: string, entry: ActivityEntry) => void;
resetSetup: () => void;
@@ -83,7 +81,6 @@ const initialState: SetupStoreState = {
discoveredTasks: [],
discoveryByRepo: {},
enricherByRepo: {},
- selectedDiscoveredTaskId: null,
};
export function selectRepoDiscovery(
@@ -265,17 +262,9 @@ export const useSetupStore = create()(
discoveredTasks: state.discoveredTasks.filter(
(t) => !(t.id === taskId && isTaskForRepo(t, repoPath)),
),
- selectedDiscoveredTaskId:
- state.selectedDiscoveredTaskId === taskId
- ? null
- : state.selectedDiscoveredTaskId,
}));
},
- selectDiscoveredTask: (taskId) => {
- set({ selectedDiscoveredTaskId: taskId });
- },
-
// Adds an enricher-source suggestion if there isn't already one with
// the same id+repoPath. Idempotent — safe to call repeatedly on every
// detection run. Dismissed suggestions stay dismissed until `resetSetup`.
diff --git a/apps/code/src/renderer/features/setup/utils/discoveredTaskToSignalReport.ts b/apps/code/src/renderer/features/setup/utils/discoveredTaskToSignalReport.ts
deleted file mode 100644
index e744a1e14..000000000
--- a/apps/code/src/renderer/features/setup/utils/discoveredTaskToSignalReport.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import type { DiscoveredTask } from "@features/setup/types";
-import type { SignalReport } from "@shared/types";
-
-export function discoveredTaskToSignalReport(
- task: DiscoveredTask,
-): SignalReport {
- const now = new Date().toISOString();
- return {
- id: task.id,
- title: task.title,
- summary: task.description,
- status: "ready",
- total_weight: 0,
- signal_count: 0,
- created_at: now,
- updated_at: now,
- artefact_count: 0,
- priority: null,
- actionability: null,
- already_addressed: null,
- is_suggested_reviewer: false,
- source_products: undefined,
- implementation_pr_url: null,
- };
-}
diff --git a/apps/code/src/renderer/features/task-detail/components/SuggestedTaskCard.tsx b/apps/code/src/renderer/features/task-detail/components/SuggestedTaskCard.tsx
index b88d2c296..c3785c6e0 100644
--- a/apps/code/src/renderer/features/task-detail/components/SuggestedTaskCard.tsx
+++ b/apps/code/src/renderer/features/task-detail/components/SuggestedTaskCard.tsx
@@ -3,7 +3,7 @@ import {
CATEGORY_CONFIG,
FALLBACK_CATEGORY_CONFIG,
} from "@features/setup/utils/categoryConfig";
-import { ArrowSquareOut, X } from "@phosphor-icons/react";
+import { X } from "@phosphor-icons/react";
import { Flex, Text, Tooltip } from "@radix-ui/themes";
import { motion } from "framer-motion";
@@ -12,7 +12,6 @@ export interface SuggestedTaskCardProps {
index: number;
onSelect: (task: DiscoveredTask) => void;
onDismiss: (task: DiscoveredTask) => void;
- onViewDetails: (task: DiscoveredTask) => void;
}
export function SuggestedTaskCard({
@@ -20,7 +19,6 @@ export function SuggestedTaskCard({
index,
onSelect,
onDismiss,
- onViewDetails,
}: SuggestedTaskCardProps) {
const config = CATEGORY_CONFIG[task.category] ?? FALLBACK_CATEGORY_CONFIG;
const TaskIcon = config.icon;
@@ -85,19 +83,6 @@ export function SuggestedTaskCard({
gap="1"
className="pointer-events-none absolute top-2 right-2 opacity-0 transition-opacity group-focus-within:pointer-events-auto group-focus-within:opacity-100 group-hover:pointer-events-auto group-hover:opacity-100"
>
-
- {
- e.stopPropagation();
- onViewDetails(task);
- }}
- className="flex h-5 w-5 shrink-0 cursor-pointer items-center justify-center rounded-md text-(--gray-9) hover:bg-(--gray-a3) hover:text-(--gray-12)"
- >
-
-
-
void;
-}
-
-export function SuggestedTasksPanel({ onSelect }: SuggestedTasksPanelProps) {
+export function SuggestedTasksPanel() {
const selectedDirectory = useActiveRepoStore((s) => s.path);
const discoveredTasks = useSetupStore((s) =>
s.discoveredTasks.filter((task) =>
@@ -50,8 +45,9 @@ export function SuggestedTasksPanel({ onSelect }: SuggestedTasksPanelProps) {
(s) => selectRepoDiscovery(s, selectedDirectory).feed,
);
const removeDiscoveredTask = useSetupStore((s) => s.removeDiscoveredTask);
- const selectDiscoveredTask = useSetupStore((s) => s.selectDiscoveredTask);
- const navigateToInbox = useNavigationStore((s) => s.navigateToInbox);
+
+ const [detailTask, setDetailTask] = useState(null);
+ const [pageStart, setPageStart] = useState(0);
const containerRef = useRef(null);
const [availableHeight, setAvailableHeight] = useState(() =>
@@ -88,14 +84,13 @@ export function SuggestedTasksPanel({ onSelect }: SuggestedTasksPanelProps) {
[removeDiscoveredTask],
);
- const handleViewDetails = useCallback(
- (task: DiscoveredTask) => {
- useInboxReportSelectionStore.getState().clearSelection();
- selectDiscoveredTask(task.id);
- navigateToInbox();
- },
- [selectDiscoveredTask, navigateToInbox],
- );
+ const handleSelectTask = useCallback((task: DiscoveredTask) => {
+ setDetailTask(task);
+ }, []);
+
+ const handleCloseDetail = useCallback(() => {
+ setDetailTask(null);
+ }, []);
const isEnricherRunning = enricherStatus === "running";
const isDiscoveryRunning = discoveryStatus === "running";
@@ -147,8 +142,23 @@ export function SuggestedTasksPanel({ onSelect }: SuggestedTasksPanelProps) {
}
}
- const visibleTasks = discoveredTasks.slice(0, visibleCount);
- const hiddenCount = totalTasks - visibleTasks.length;
+ // Clamp pageStart if dismissals shrink the list past the current page.
+ const effectivePageStart =
+ visibleCount > 0 && pageStart < totalTasks ? pageStart : 0;
+
+ const visibleTasks = discoveredTasks.slice(
+ effectivePageStart,
+ effectivePageStart + visibleCount,
+ );
+ const hiddenCount = totalTasks - visibleCount;
+
+ const handleSeeMore = () => {
+ setPageStart((prev) => {
+ const base = prev < totalTasks ? prev : 0;
+ const next = base + visibleCount;
+ return next >= totalTasks ? 0 : next;
+ });
+ };
const fadeMotion = {
initial: { opacity: 0 },
@@ -170,9 +180,8 @@ export function SuggestedTasksPanel({ onSelect }: SuggestedTasksPanelProps) {
key={task.id}
task={task}
index={index}
- onSelect={onSelect}
+ onSelect={handleSelectTask}
onDismiss={handleDismiss}
- onViewDetails={handleViewDetails}
/>
))}
{hiddenCount > 0 && (
@@ -180,13 +189,13 @@ export function SuggestedTasksPanel({ onSelect }: SuggestedTasksPanelProps) {
key="see-more"
layout
type="button"
- onClick={navigateToInbox}
+ onClick={handleSeeMore}
{...fadeMotion}
className="cursor-pointer self-end rounded-md px-1.5 py-0.5 text-(--gray-11) hover:text-(--gray-12)"
>
- See {hiddenCount} more in Inbox
+ See {hiddenCount} more
@@ -220,6 +229,10 @@ export function SuggestedTasksPanel({ onSelect }: SuggestedTasksPanelProps) {
)}
+
);
}
diff --git a/apps/code/src/renderer/features/task-detail/components/TaskInput.tsx b/apps/code/src/renderer/features/task-detail/components/TaskInput.tsx
index 3fdf72070..9a3b7ae7a 100644
--- a/apps/code/src/renderer/features/task-detail/components/TaskInput.tsx
+++ b/apps/code/src/renderer/features/task-detail/components/TaskInput.tsx
@@ -23,9 +23,6 @@ import { UnifiedModelSelector } from "@features/sessions/components/UnifiedModel
import { getCurrentModeFromConfigOptions } from "@features/sessions/stores/sessionStore";
import type { AgentAdapter } from "@features/settings/stores/settingsStore";
import { useSettingsStore } from "@features/settings/stores/settingsStore";
-import { useSetupStore } from "@features/setup/stores/setupStore";
-import type { DiscoveredTask } from "@features/setup/types";
-import { buildDiscoveredTaskPrompt } from "@features/setup/utils/buildDiscoveredTaskPrompt";
import { useAutoFocusOnTyping } from "@hooks/useAutoFocusOnTyping";
import { useConnectivity } from "@hooks/useConnectivity";
import {
@@ -538,18 +535,6 @@ export function TaskInput({
editorRef.current?.setContent(text);
editorRef.current?.focus();
}, []);
- const handleSelectSuggestion = useCallback(
- async (task: DiscoveredTask) => {
- const ok = await handleSubmit({
- segments: [{ type: "text", text: buildDiscoveredTaskPrompt(task) }],
- });
- if (ok)
- useSetupStore
- .getState()
- .removeDiscoveredTask(task.id, task.repoPath ?? null);
- },
- [handleSubmit],
- );
const hasPendingDraft = useCallback(
() => !(editorRef.current?.isEmpty() ?? true),
[],
@@ -842,7 +827,7 @@ export function TaskInput({
)}
-
+