diff --git a/app/src/components/intelligence/MemorySection.test.tsx b/app/src/components/intelligence/MemorySection.test.tsx new file mode 100644 index 000000000..32b8bc87d --- /dev/null +++ b/app/src/components/intelligence/MemorySection.test.tsx @@ -0,0 +1,47 @@ +import { screen } from '@testing-library/react'; +import { describe, expect, it, vi } from 'vitest'; + +import { renderWithProviders } from '../../test/test-utils'; +import type { ToastNotification } from '../../types/intelligence'; +import MemorySection from './MemorySection'; + +const memoryWorkspaceSpy = + vi.fn<(props: { onToast?: (toast: Omit) => void }) => void>(); + +vi.mock('./MemoryWorkspace', () => ({ + MemoryWorkspace: (props: { onToast?: (toast: Omit) => void }) => { + memoryWorkspaceSpy(props); + return
; + }, +})); + +describe('', () => { + it('renders the core MemoryWorkspace directly with no analysis sub-pill bar', () => { + const onToast = vi.fn(); + renderWithProviders(); + + // Core view is shown. + expect(screen.getByTestId('memory-workspace')).toBeInTheDocument(); + + // No sub-pill/tab bar (the analysis pills are gone). + for (const label of [ + 'Diagram', + 'Centrality', + 'Cohesion', + 'Associations', + 'Freshness', + 'Timeline', + 'Paths', + 'Namespaces', + ]) { + expect(screen.queryByRole('button', { name: label })).not.toBeInTheDocument(); + } + }); + + it('forwards onToast to MemoryWorkspace', () => { + const onToast = vi.fn(); + renderWithProviders(); + + expect(memoryWorkspaceSpy).toHaveBeenCalledWith(expect.objectContaining({ onToast })); + }); +}); diff --git a/app/src/components/intelligence/MemorySection.tsx b/app/src/components/intelligence/MemorySection.tsx index d9e491593..7dd6b2064 100644 --- a/app/src/components/intelligence/MemorySection.tsx +++ b/app/src/components/intelligence/MemorySection.tsx @@ -1,76 +1,22 @@ -import { useState } from 'react'; - -import { useT } from '../../lib/i18n/I18nContext'; import type { ToastNotification } from '../../types/intelligence'; -import { IS_DEV } from '../../utils/config'; -import PillTabBar from '../PillTabBar'; -import ConnectionPathTab from './ConnectionPathTab'; -import DiagramViewerTab from './DiagramViewerTab'; -import EntityAssociationsTab from './EntityAssociationsTab'; -import GraphCentralityTab from './GraphCentralityTab'; -import GraphCohesionTab from './GraphCohesionTab'; -import MemoryFreshnessTab from './MemoryFreshnessTab'; -import MemoryTimelineTab from './MemoryTimelineTab'; import { MemoryWorkspace } from './MemoryWorkspace'; -import NamespaceOverviewTab from './NamespaceOverviewTab'; /** - * Memory sub-tabs. + * Memory tab body. * - * All graph/memory-analysis surfaces that previously lived as top-level - * Intelligence tabs are nested here under the "Memory" tab. The first sub-tab - * (`memoryTree`) is the former top-level "Memory" tab (the MemoryWorkspace). + * Renders the core memory experience (`MemoryWorkspace` — sources registry, + * tree-status panel, and summary graph) directly, with no sub-pill/tab bar. + * + * The internal graph/memory-analysis surfaces (Diagram, Centrality, Cohesion, + * Associations, Freshness, Timeline, Paths, Namespaces) are developer/analysis + * views that cluttered the experience and are intentionally no longer reachable + * from this tab. Their components are retained on disk (and still unit-tested) + * so they can be restored behind a dedicated surface later if needed. */ -type MemorySubTab = - | 'memoryTree' - | 'diagram' - | 'centrality' - | 'cohesion' - | 'associations' - | 'freshness' - | 'timeline' - | 'paths' - | 'namespaces'; - interface MemorySectionProps { onToast: (toast: Omit) => void; } export default function MemorySection({ onToast }: MemorySectionProps) { - const { t } = useT(); - const [activeSubTab, setActiveSubTab] = useState('memoryTree'); - - const allSubTabs: { id: MemorySubTab; label: string; devOnly?: boolean }[] = [ - { id: 'memoryTree', label: t('memory.tab.memoryTree') }, - { id: 'diagram', label: t('memory.tab.diagram'), devOnly: true }, - { id: 'centrality', label: t('memory.tab.centrality'), devOnly: true }, - { id: 'cohesion', label: t('memory.tab.cohesion'), devOnly: true }, - { id: 'associations', label: t('memory.tab.associations'), devOnly: true }, - { id: 'freshness', label: t('memory.tab.freshness'), devOnly: true }, - { id: 'timeline', label: t('memory.tab.timeline'), devOnly: true }, - { id: 'paths', label: t('memory.tab.path'), devOnly: true }, - { id: 'namespaces', label: t('memory.tab.namespaces'), devOnly: true }, - ]; - const subTabs = allSubTabs.filter(tab => !tab.devOnly || IS_DEV); - - return ( -
- ({ label: tab.label, value: tab.id }))} - selected={activeSubTab} - onChange={setActiveSubTab} - containerClassName="flex flex-wrap gap-2 pb-1" - /> - - {activeSubTab === 'memoryTree' && } - {activeSubTab === 'diagram' && } - {activeSubTab === 'centrality' && } - {activeSubTab === 'cohesion' && } - {activeSubTab === 'associations' && } - {activeSubTab === 'freshness' && } - {activeSubTab === 'timeline' && } - {activeSubTab === 'paths' && } - {activeSubTab === 'namespaces' && } -
- ); + return ; }