2368764251
Core: - IEspoCrmClient.ListCasesForContactAsync (paged where[]=linkedWith query) - EspoListResponse<T> generic envelope for /list endpoints - IMatchingService + MatchingService: EmailAddress/search → Contact → Account → recent 5 Cases. MemoryCache 10-min TTL; caches null and ambiguous results too. Returns null for 0 matches, IsAmbiguous=true for 2+, populated MatchResult for exactly 1. - MatchResult DTO with Contact / Account / RecentCases / IsAmbiguous UI: - ReadingPaneView (WPF UserControl, RTL): 6 states — Empty / Loading / Match / NoMatch / Ambiguous / Error — switched via Visibility bindings - ReadingPaneViewModel: state machine, FileRequested + OpenInBrowserRequested events, Reset()/LoadAsync() with cancellation chain (every selection cancels the previous lookup) Host: - ExplorerSelectionHandler: subscribes to Outlook.Explorer.SelectionChange, 200ms debounce via Timer, dedupes by last sender, marshals to WPF dispatcher before reading COM state - SidebarController: attaches a CustomTaskPane per Explorer (ElementHost wrapping ReadingPaneView), tracks bindings by COM identity, unhooks on Explorer.Close. Sidebar defers attach until CRM client is configured (subscribes to CrmClientChanged) - AddInHost: MatchingService field, MemoryCache shared across lookups, InitializeSidebar(taskPanes) invoked from ThisAddIn_Startup Core/UI/Tests green (38 tests passing); VSTO host still needs VS Installer Repair locally. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>