UXS-005: Semantic Search Panel¶
- Status: Active (main-column query surface superseded by UXS-016 Query Workspace once RFC-107 lands; UXS-005 continues to specify the compact launcher role of the left column on non-Search tabs — see the "Compact launcher (RFC-107)" section near the end)
- Authors: Podcast Scraper Team
- Parent UXS: UXS-001: GI/KG Viewer -- shared tokens, typography, layout, states
- Related PRDs:
- PRD-021: Semantic Corpus Search
- Related RFCs:
- RFC-061: Semantic Corpus Search
- RFC-062: GI/KG viewer v2
- RFC-072: Canonical identity + cross-layer bridge (chunk-to-Insight lift on transcript hits)
- RFC-075: Corpus Topic Clustering (optional Show on graph / cluster follow-ups)
- RFC-090: Hybrid Retrieval — hybrid is now the default backend; FAISS retained as fallback
- RFC-094: Surfaces Query Layer — relational queries the surfaces consume
Alignment (2026-06-04). The backend shipped: hybrid retrieval (BM25 + dense via RRF over LanceDB, with compound results) is the default — FAISS is the fallback. The surface plan is re-grounded in PRD-033 (FR1) over the RFC-094 query layer; this surface is tracked in #884.
- Implementation paths:
web/gi-kg-viewer/src/components/shell/LeftPanel.vue(hosts the search column)web/gi-kg-viewer/src/components/search/SearchPanel.vueweb/gi-kg-viewer/src/components/search/ResultCard.vueweb/gi-kg-viewer/src/components/search/SearchResultsVizDialog.vueweb/gi-kg-viewer/src/components/search/SemanticSearchTip.vueweb/gi-kg-viewer/src/stores/search.ts(exposesqueryTypefor FR1.4)src/podcast_scraper/server/routes/search.py(#884) — surfacessource_tierper hit + responsequery_type(additive; FAISS + hybrid consistent)- Shell IA: VIEWER_IA.md — left panel Search + Explore, navigation axes, subject rail, status bar
Placement¶
Search is the default surface of the left query column; Explore is an alternate mode
(slide transition) entered via a quiet footer control (Explore corpus →) and exited via
← Search — see VIEWER_IA.md. Mode is shell.leftPanelSurface (search |
explore). / expands the column if needed, switches to Search, then focuses #search-q
(LeftPanel → focusQuery). LeftPanel.vue hosts SearchPanel.vue + ExplorePanel.vue
at w-72 when expanded. Search results stay visible when a hit opens in the subject rail
(mode switches do not clear the subject). Deprecated: right-rail-only search, episodeRail,
paneKind = tools as placement drivers.
Summary¶
For shell layout, the three navigation axes, subject rail persistence and clearing, status bar, and first-run empty corpus behavior, see VIEWER_IA.md. This document specifies the Search and Explore panel content only (query form, advanced filters, result cards, insights modal).
The search panel provides corpus search (hybrid by default, FAISS fallback) in the left shell column
(Semantic search card: form + scrollable results; Explore corpus → sits in LeftPanel
below that card). This UXS defines the visual contract for the search form,
advanced filters, result cards, and the search result insights modal. All tokens reference
UXS-001.
Track shell work in GitHub #606 and RFC-062. When the viewer changes, update this Active UXS in the same PR — see Living documents and ship boundary.
RFC-075: When corpus clustering JSON is available, Show on graph from search still selects the
leaf node id (e.g. topic:…) as today. The graph node rail shows Topic cluster: for Topic
nodes (Phase 1; see UXS-004). Search result cards may show a
Topic cluster: line when the API joined metadata.topic_cluster (canonical label and compound
id). Show on graph may widen the camera to include the tc: compound parent while keeping
selection on the leaf. The pan/zoom animation and minimum zoom floor for that hand-off match
other graph focus paths (UXS-004 — Camera framing and selection).
Dashboard topic clusters: On the Dashboard → Intelligence sub-tab, the Topic clusters
status block reflects GET /api/corpus/topic-clusters
as soon as Corpus path is set and health is OK — you do not need to wait for GI/KG
artifacts to finish loading into the graph. While the request is in flight, Status shows Checking….
Then: Loaded, Not built (404 — optional
topic-clusters CLI), request error, or Local files only when the graph came from the file
picker (no API fetch for clustering). Unknown schema_version values get a non-blocking warning line.
Primary flow¶
Search query field (no separate label; placeholder + Semantic search heading) —
Enter submits the same as Search (disabled while loading / no corpus / API down);
Shift+Enter inserts a newline; IME composition does not trigger submit.
Then a filter chip bar (#671, data-testid="search-filter-bar") with four chips —
Since (search-chip-since, shared DateChip), Top‑k (search-chip-topk,
default 10), Doc types (search-chip-doctypes, empty = all), More
(search-chip-more, opens the slim Advanced search dialog). Each chip's label
switches from Label ▾ (default) to Label: detail ▾ when active; the More
chip shows More: N reflecting the count of non-default fields it hosts. Replaces
the legacy inline Since (date) + Top-k row, the "Advanced search" underline link,
and the read-only "Active advanced filters" summary block (which is gone — chip
labels carry the active state instead). Search / Clear sit below the chip
bar; scrollable results (errors + hit cards) follow in the middle.
Explore mode has been retired — see the "Explore mode retired" note
below for the current state (filters folded into the Workspace filter
chip bar).
Advanced search dialog (slim, hosted by the More chip)¶
Opened by clicking the More filter chip; same backdrop pattern as before. After #671 the dialog hosts only the low-traffic fields that aren't worth a top-level chip:
- Feed (substring on catalog
feed_idfor the API; Library -> Prefill semantic search shows the feed title from the feeds catalog when known, with hover/title for the id until edited) - Grounded insights only
- Speaker contains
- Embedding model
- Merge duplicate KG surfaces (default on: same behavior family as graph
Entity/Topic dedupe for
kg_entity/kg_topicvector rows)
The legacy in-dialog Doc Types fieldset moved to the dedicated Doc types chip on the filter bar.
Search result insights¶
After at least one hit, an underlined Search result insights control opens a
modal (same backdrop pattern as Advanced search) titled "Search result insights" --
one scroll, no tabs: a short insight line (dominant doc type); Doc types and
Publish month in a two-column row (small multiples); Episodes / Feeds
with top rows (episode title / feed title from hit metadata, or loaded from the
episode's *.metadata.json when the index row omitted them) plus "+N other..." tail
counts; Similarity bars proportional to score / max(score) in the list
(captioned); Terms with a top-token insight (word frequency; heuristic, not KG).
Results¶
A muted "N results" / "1 result" line only (the query stays in the textarea; it is
not repeated here). When the API returns lift_stats and at least one transcript
row is on the page, a compact Lift: applied / transcript rows ratio appears on
the same row (native title explains RFC-072 lift coverage).
Each hit can expose:
- G (graph focus, GI token) and L (Library episode) as separate controls
- L requires a healthy API check + corpus path and
source_metadata_relative_pathon the hit (vector indexer stamps it on rebuild) corpus_library_apiin health can still be No while L shows; the Library tab surfaces errors if catalog routes are unavailable- E (episode id chip) is informational
- When Merge duplicate KG surfaces merged a row (
kg_surface_match_count>= 2), G only -- L and E are hidden so actions are not tied to a single representative episode - Transcript hits may include a collapsible
regionLifted GI insight (linked insight id/text, speaker/topic labels, quote time range) when the server attacheslifted(#528). Whenlifted.quotehas at least one finitetimestamp_*_msbutlifted.speakerhas no usable display label, a muted line shows the same visible copy as supporting quotes — No speaker detected (GI_QUOTE_SPEAKER_UNAVAILABLE_HINT; #541).data-testid="search-lifted-quote-speaker-unavailable". - Supporting quotes (Show / Hide N supporting quote(s)): when the API returns
supporting_quotesand a quote has nospeaker_name/speaker_id, a muted line shows No speaker detected (sameGI_QUOTE_SPEAKER_UNAVAILABLE_HINTas the graph Quote rail; #541).data-testid="supporting-quote-speaker-unavailable".
Two-tier results, evidence toggle, and intent (PRD-033 FR1)¶
The platform now indexes and ranks two primary tiers (synthesized insights + raw transcript segments) plus an auxiliary tier (kg_entity / kg_topic / quote / summary). The search surface makes that legible without re-querying:
- Tier badge (FR1.1). Every hit card carries a small tier badge
(
search-result-tier): Insight (primary), Transcript (success), or Reference (muted), from the server-derivedsource_tier. Named-entity queries surface exact matches through retrieval quality (FR1.2) — no separate UI. - Compound result (FR1.1). A transcript (
segment) hit that lifts a linked GI insight is a compound — the card shows both the segment text and the linked insight (the existing Lifted GI insight block) and is marked with a+ insightbadge (search-result-compound). - Evidence toggle (FR1.3). A small Insights / Transcript / Both segmented
control (
search-evidence-toggle) in the results header constrains the rendered cards to a tier (Both = no constraint). Client-side over the returned page; the active button usesaria-pressed. - Query-type indicator (FR1.4). When the response carries a detected intent, an
Intent:
<label>chip (search-query-type) sits in the results header (Entity lookup / Raw evidence / Temporal tracking / Cross-show synthesis / Semantic). Transparency only — the platform adapts its retrieval strategy per the rules router (RFC-090 §3.6); it does not change what the user must do. - Entity links to Detail (FR1.5). Canonical speaker / topic / entity names resolve
to their Detail rail: lifted speaker → Person Landing
(
search-result-lifted-speaker-link), lifted topic → Topic Entity View (search-result-lifted-topic-link), and akg_entity/kg_topichit links itssource_idvia Open Person/Topic panel → (search-result-entity-link). Supporting-quote speakers keep their existing Person link.
E2E contract¶
E2E surface map -- search panel surfaces and selectors.
Compact launcher (RFC-107)¶
Once Search v3 (RFC-107) lands, the primary query surface moves to the full-width Query Workspace (UXS-016). UXS-005 continues to govern the compact launcher the LeftPanel becomes on non-Search tabs:
- Single query field (
#search-q— same testid as today). - Last-N recent queries (from USERPREFS-1
search.recentQueries— see ADR-125). - "Open in Workspace" chip; Enter submits and switches the main tab to Search.
- Explore mode retired. The slide mode-switch,
shell.leftPanelSurface = 'explore', and theleft-panel-enter-explore/left-panel-back-searchtest IDs are removed. Explore's filters (topic contains / speaker contains / limit / min confidence / grounded only / presets) fold into the Workspace filter chip bar (UXS-016 §Header). - On the Search tab, the LeftPanel is hidden (Workspace owns full width).
- Enriched answers are never invoked from the compact launcher — Workspace only.
The Advanced-search dialog treatment described above continues to apply on the Workspace filter
chip bar's More chip; the Enriched answers toggle previously in that dialog is retired (replaced
by the header Enriched chip in UXS-016).
Revision history¶
| Date | Change |
|---|---|
| 2026-04-21 | Query: Enter submits search; Shift+Enter newline; IME-safe. |
| 2026-04-21 | Explore CTA: LeftPanel footer below search card (clears status bar). |
| 2026-04-21 | Left column: Search default; Explore mode (slide); / restores Search + focus. |
| 2026-04-21 | Search: Since + Top-k row uses grid so fields stay in panel. |
| 2026-04-21 | Show on graph: UXS-004 camera + min zoom (cross-link). |
| 2026-04-06 | Initial content (in UXS-001) |
| 2026-04-13 | Extracted from UXS-001 into standalone UXS-005 |
| 2026-04-13 | Document lift_stats summary line + Lifted GI insight region |
| 2026-04-15 | Supporting quotes: muted hint when speaker missing (#541) |
| 2026-06-05 | PRD-033 FR1: tier/compound badges, evidence toggle, intent chip, entity links (#884) |
| 2026-04-15 | Lifted GI: muted hint + testid when speaker display missing (#541) |
| 2026-04-15 | Lifted hint only when lifted.quote has finite timestamp_*_ms (matches E2E) |
| 2026-04-15 | #541: No speaker detected (graph + Search + Explore; semantics unchanged) |
| 2026-04-16 | Lifted GI: explicit same visible string as supporting quotes (No speaker detected) |
| 2026-04-19 | Shell IA: left query column copy; topic clusters card under Dashboard workspace (#606) |