From 0187facbc03eda8a722ebc3caf45eeaa1b66adc7 Mon Sep 17 00:00:00 2001 From: Linjie-top Date: Fri, 13 Mar 2026 18:03:35 +0800 Subject: [PATCH 1/5] chore(research): snapshot before removing post-search component --- web/.npm-cache/_update-notifier-last-checked | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 web/.npm-cache/_update-notifier-last-checked diff --git a/web/.npm-cache/_update-notifier-last-checked b/web/.npm-cache/_update-notifier-last-checked new file mode 100644 index 00000000..e69de29b From 7e9802d07066b872eca62a1bb8f2a4e50ff0b55d Mon Sep 17 00:00:00 2001 From: Linjie-top Date: Fri, 13 Mar 2026 18:16:32 +0800 Subject: [PATCH 2/5] refactor(research): remove post-search track context panel --- web/src/components/research/ResearchPageNew.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/web/src/components/research/ResearchPageNew.tsx b/web/src/components/research/ResearchPageNew.tsx index 746b2443..a8862b31 100644 --- a/web/src/components/research/ResearchPageNew.tsx +++ b/web/src/components/research/ResearchPageNew.tsx @@ -41,7 +41,6 @@ import { SavedTab } from "./SavedTab" import { CreateTrackModal } from "./CreateTrackModal" import { EditTrackModal } from "./EditTrackModal" import { ManageTracksModal } from "./ManageTracksModal" -import { ResearchTrackContextPanel } from "./ResearchTrackContextPanel" import type { Track } from "./TrackSelector" import type { Paper } from "./PaperCard" import type { ResearchTrackContextResponse } from "@/lib/types" @@ -638,14 +637,7 @@ export default function ResearchPageNew() { /> - {trackContext ? ( -
- setMemoryOpen(true)} - /> -
- ) : null} + {/* Track context panel removed per request */} {/* Track Pills - only show before search */} {!hasSearched && tracks.length > 0 && ( From 3b4db94e5cbbd885fa79545601bcbf7d38111bbe Mon Sep 17 00:00:00 2001 From: Linjie-top Date: Fri, 13 Mar 2026 18:21:15 +0800 Subject: [PATCH 3/5] chore(research): remove unused ResearchTrackContextPanel and test --- .../ResearchTrackContextPanel.test.tsx | 76 ------- .../research/ResearchTrackContextPanel.tsx | 213 ------------------ 2 files changed, 289 deletions(-) delete mode 100644 web/src/components/research/ResearchTrackContextPanel.test.tsx delete mode 100644 web/src/components/research/ResearchTrackContextPanel.tsx diff --git a/web/src/components/research/ResearchTrackContextPanel.test.tsx b/web/src/components/research/ResearchTrackContextPanel.test.tsx deleted file mode 100644 index c1a6dac1..00000000 --- a/web/src/components/research/ResearchTrackContextPanel.test.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { describe, expect, it } from "vitest" -import { renderToStaticMarkup } from "react-dom/server" - -import type { ResearchTrackContextResponse } from "@/lib/types" - -import { ResearchTrackContextPanel, buildStatItems } from "./ResearchTrackContextPanel" - -const TRACK_CONTEXT_FIXTURE: ResearchTrackContextResponse = { - user_id: "default", - track_id: 7, - track: { - id: 7, - name: "Agentic Retrieval", - description: "Keep retrieval quality and latency balanced.", - keywords: ["rag", "retrieval", "reranking"], - is_active: true, - }, - tasks: [ - { id: 1, track_id: 7, title: "Validate reranker", status: "todo" }, - { id: 2, track_id: 7, title: "Compare OpenAlex recall", status: "doing" }, - ], - milestones: [ - { id: 9, track_id: 7, name: "Freeze benchmark slice", status: "doing" }, - ], - memory: { - total_items: 6, - approved_items: 4, - pending_items: 2, - top_tags: ["retrieval", "latency"], - latest_memory_at: "2026-03-12T08:00:00+00:00", - }, - feedback: { - total_items: 5, - actions: { save: 3, like: 2 }, - latest_feedback_at: "2026-03-12T08:30:00+00:00", - recent_items: [], - }, - saved_papers: { - total_items: 3, - latest_saved_at: "2026-03-12T08:40:00+00:00", - recent_items: [], - }, - eval_summary: { - feedback_coverage: 0.75, - }, -} - -describe("ResearchTrackContextPanel", () => { - it("builds compact stat cards from the track snapshot", () => { - const stats = buildStatItems(TRACK_CONTEXT_FIXTURE) - - expect(stats).toHaveLength(3) - expect(stats.map((item) => ({ label: item.label, value: item.value }))).toEqual([ - { label: "Pending Memory", value: "2" }, - { label: "Saved Papers", value: "3" }, - { label: "Feedback", value: "5" }, - ]) - }) - - it("renders the consolidated track snapshot details", () => { - const html = renderToStaticMarkup( - undefined} - /> - ) - - expect(html).toContain("Track Snapshot") - expect(html).toContain("Agentic Retrieval") - expect(html).toContain("Pending Memory") - expect(html).toContain("Validate reranker") - expect(html).toContain("Freeze benchmark slice") - expect(html).toContain("save: 3") - expect(html).toContain("75%") - }) -}) diff --git a/web/src/components/research/ResearchTrackContextPanel.tsx b/web/src/components/research/ResearchTrackContextPanel.tsx deleted file mode 100644 index 51841a61..00000000 --- a/web/src/components/research/ResearchTrackContextPanel.tsx +++ /dev/null @@ -1,213 +0,0 @@ -"use client" - -import { BookMarked, BrainCircuit, CheckSquare2, Clock3, Database, Tags } from "lucide-react" - -import { Badge } from "@/components/ui/badge" -import { Button } from "@/components/ui/button" -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" -import { Separator } from "@/components/ui/separator" -import type { - ResearchTrackContextResponse, - ResearchTrackSummary, -} from "@/lib/types" - -type StatItem = { - label: string - value: string - icon: typeof Database -} - -export function buildStatItems(context: ResearchTrackContextResponse): StatItem[] { - return [ - { - label: "Pending Memory", - value: String(context.memory.pending_items), - icon: Clock3, - }, - { - label: "Saved Papers", - value: String(context.saved_papers.total_items), - icon: BookMarked, - }, - { - label: "Feedback", - value: String(context.feedback.total_items), - icon: BrainCircuit, - }, - ] -} - -function getTrackDescription(track: ResearchTrackSummary): string { - const description = String(track.description || "").trim() - if (description) { - return description - } - const keywords = track.keywords || [] - if (keywords.length > 0) { - return `Focused on ${keywords.slice(0, 4).join(", ")}.` - } - return "Use the track snapshot to keep context, memory, and saved papers aligned." -} - -interface ResearchTrackContextPanelProps { - context: ResearchTrackContextResponse - onOpenMemory: () => void -} - -export function ResearchTrackContextPanel({ - context, - onOpenMemory, -}: ResearchTrackContextPanelProps) { - const statItems = buildStatItems(context) - const track = context.track - const keywords = track.keywords || [] - const memoryTags = context.memory.top_tags || [] - - return ( - - -
-
-
- Track Snapshot - {track.is_active ? Active Track : null} -
-
- {track.name} -

{getTrackDescription(track)}

-
-
- -
-
- -
- {statItems.map((item) => { - const Icon = item.icon - return ( -
-
- - {item.label} -
-
{item.value}
-
- ) - })} -
- - {keywords.length > 0 ? ( -
- - - Track Keywords - - {keywords.slice(0, 6).map((keyword) => ( - - {keyword} - - ))} -
- ) : null} - - - -
-
-
- -

Recent Track Work

-
-
-
-

Tasks

-
- {context.tasks.length > 0 ? ( - context.tasks.slice(0, 3).map((task) => ( -
-
{task.title}
-
- Status {task.status || "todo"} -
-
- )) - ) : ( -

No tasks yet for this track.

- )} -
-
- -
-

Milestones

-
- {context.milestones.length > 0 ? ( - context.milestones.slice(0, 3).map((milestone) => ( -
-
{milestone.name}
-
- Status {milestone.status || "todo"} -
-
- )) - ) : ( -

No milestones yet for this track.

- )} -
-
-
-
- -
-

Memory & Feedback Shape

-
-
-
Approved Memory
-
{context.memory.approved_items}
-
-
-
Feedback Coverage
-
- {Math.round(Number(context.eval_summary.feedback_coverage || 0) * 100)}% -
-
-
-
-
Top Memory Tags
-
- {memoryTags.length > 0 ? ( - memoryTags.map((tag) => ( - - {tag} - - )) - ) : ( - No track-scoped memory tags yet. - )} -
-
-
-
Effective Feedback Mix
-
- {Object.entries(context.feedback.actions).length > 0 ? ( - Object.entries(context.feedback.actions).map(([action, count]) => ( - - {action}: {count} - - )) - ) : ( - No effective feedback recorded yet. - )} -
-
-
-
-
-
- ) -} From 5a1b01ed25eb814dcef6305275be6a060503bfe6 Mon Sep 17 00:00:00 2001 From: Linjie-top Date: Fri, 13 Mar 2026 21:54:17 +0800 Subject: [PATCH 4/5] test(research): assert Track Snapshot panel removed and post-search UI remains --- web/e2e/research.spec.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/web/e2e/research.spec.ts b/web/e2e/research.spec.ts index c25e0ef7..197e4b61 100644 --- a/web/e2e/research.spec.ts +++ b/web/e2e/research.spec.ts @@ -25,4 +25,21 @@ test.describe("Research Page E2E", () => { content?.includes("Topic"); expect(hasResearchContent).toBeTruthy(); }); + + test("post-search view renders without Track Snapshot panel", async ({ page }) => { + // Navigate with a query to trigger post-search UI state + await page.goto("/research?query=rag"); + await page.waitForLoadState("networkidle"); + + // The old panel label should not appear anymore + const body = page.locator("body"); + await expect(body).not.toContainText("Track Snapshot"); + + // Basic sanity: post-search summary badges/cta remain + // We don't depend on backend success; the UI switches to post-search immediately + const summaryHints = ["Results:", "Mode:", "Sources:"]; + const text = await body.textContent(); + const anyPresent = summaryHints.some((t) => (text || "").includes(t)); + expect(anyPresent).toBeTruthy(); + }); }); From 808ac57e65b3e692c880e0234d0f311da160a966 Mon Sep 17 00:00:00 2001 From: Linjie-top Date: Fri, 13 Mar 2026 22:08:12 +0800 Subject: [PATCH 5/5] test(research): wait for post-search state before asserting removed panel --- web/e2e/research.spec.ts | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/web/e2e/research.spec.ts b/web/e2e/research.spec.ts index 197e4b61..a1b63d5d 100644 --- a/web/e2e/research.spec.ts +++ b/web/e2e/research.spec.ts @@ -29,17 +29,14 @@ test.describe("Research Page E2E", () => { test("post-search view renders without Track Snapshot panel", async ({ page }) => { // Navigate with a query to trigger post-search UI state await page.goto("/research?query=rag"); - await page.waitForLoadState("networkidle"); - // The old panel label should not appear anymore - const body = page.locator("body"); - await expect(body).not.toContainText("Track Snapshot"); + // 1) Wait for a stable post-search marker (auto-retrying) + await expect(page.getByRole("link", { name: "Open Workflows" })).toBeVisible(); + + // 2) Assert the old panel label is absent (auto-retrying) + await expect(page.locator("text=Track Snapshot")).toHaveCount(0); - // Basic sanity: post-search summary badges/cta remain - // We don't depend on backend success; the UI switches to post-search immediately - const summaryHints = ["Results:", "Mode:", "Sources:"]; - const text = await body.textContent(); - const anyPresent = summaryHints.some((t) => (text || "").includes(t)); - expect(anyPresent).toBeTruthy(); + // 3) Sanity: a summary badge/label remains visible (one is enough) + await expect(page.locator("text=Results:").first()).toBeVisible(); }); });