feat: user patterns analysis + security hardening#16
Merged
kevintseng merged 36 commits intomainfrom Apr 19, 2026
Merged
Conversation
…ating The overwrite merge strategy previously archived the entity then called createEntity(), which has reactivation logic that un-archives and APPENDS new observations to the old ones. Now uses clearEntityData() to delete observations + tags (keeping the entity row) before re-populating, ensuring overwrite truly replaces content.
exportMemories() previously applied namespace filter AFTER the SQL LIMIT, so if limit=10 and the first 10 entities were all 'personal', requesting namespace='team' returned 0 results even if team entities existed. Now passes namespace directly to kg.search() which applies the filter in the SQL WHERE clause before LIMIT.
Add embedder.ts with local ONNX embedding generation using Xenova/all-MiniLM-L6-v2. Provides isEmbeddingAvailable(), embedText(), embedAndStore(), and vectorSearch() — all gracefully degrade when the package is missing. Fire-and-forget design keeps remember() synchronous.
- remember(): fire-and-forget embedAndStore() after entity creation (non-blocking, keeps function synchronous) - recallEnhanced(): vector search supplements FTS5 results in both LLM expansion path and Level 0 fallback path - Graceful degradation: if embeddings unavailable, search falls back to FTS5-only (no behavioral change for existing users)
Graph tab: force-directed canvas visualization of entity relationships with drag, hover tooltips, and type-based coloring. No external deps. Lessons tab: structured lesson_learned cards with parsed Error/Root cause/Fix/Prevention fields, severity coloring, and confidence badges. Both tabs include translations for all 11 supported languages.
…ph + Lessons - Neural embeddings: @xenova/transformers (all-MiniLM-L6-v2, 384-dim) integrated into remember (fire-and-forget) and recallEnhanced (hybrid search) - Fix overwrite import: clearEntityData() replaces archive+reactivate - Fix namespace export: filter at query level, not post-filter - Dashboard: 7 tabs (+ Graph with force-directed canvas, + Lessons with cards) - 402 tests across 25 files
Replace generic Inter/zinc/blue aesthetic with distinctive design: - Satoshi font (Fontshare) + Geist Mono (Google Fonts) - Cyan accent #00D6B4 replacing overused blue-500 - Compact 4px spacing, 8px radius, zero decoration - All hardcoded colors in LessonsTab/GraphTab replaced with design system tokens - DESIGN.md added as single source of truth for all visual decisions Co-Authored-By: Claude <noreply@anthropic.com>
…polish - FeedbackWidget component: type selection (Bug/Feature/Question), description textarea, system info toggle, opens pre-filled GitHub issue - Full i18n: 7 new keys across all 11 locales - Restore interaction feedback: header backdrop-filter, card/stat hover shadows, input focus ring, feedback button lift effect, connection dot glow Co-Authored-By: Claude <noreply@anthropic.com>
- FINDING-001/002/003: nav tabs min-height 44px, pagination buttons enlarged, border-bottom widened to 2px for better active indicator - FINDING-005: search tab shows hint text when no search performed (i18n: search.hint added to all 11 locales) Co-Authored-By: Claude <noreply@anthropic.com>
…l 11 locales AnalyticsTab now fetches from both /v1/stats and /v1/analytics in parallel, rendering HealthScore, MemoryTimeline, ValueMetrics, and CleanupSuggestions components. Added 24 new i18n keys across all 11 locales (en, zh-TW, zh-CN, ja, ko, pt, fr, de, vi, es, th).
…e, type distribution
- HealthFactor: number → {score, weight, detail} object
- Timeline: day → date field name
- ValueMetrics: lessonsSaved → lessonsWithWarnings
Co-Authored-By: Claude <noreply@anthropic.com>
…, recency heatmap, orphans - Type filter checkboxes: toggle visibility per entity type with colored dots - Search with highlight: 260px input, cyan glow ring on matches, auto-center single match - Ego graph: click node to focus on 1-degree neighborhood, banner with Show All - Recency heatmap: opacity based on last_accessed_at age (0.15-1.0 range) - Orphan indicator: dashed border for zero-relation nodes, 3rd stat card - Tooltip shows name, type, and age; edge labels hidden when >30 visible edges - Node labels only on hover/focus/match to reduce clutter - Performance: skip distant repulsion pairs for N>200 nodes - i18n: added graph.orphans/search/matches/focusMode/showAll/clickHint to all 11 locales
useEffect with [data] dependency fired while loading=true, when the canvas element wasn't in the DOM yet (loading spinner rendered instead). Added loading to dependency array and early return guard. Co-Authored-By: Claude <noreply@anthropic.com>
CRITICAL: /v1/analytics staleEntities query now returns id + days_unused (was returning last_accessed_at without id — frontend contract mismatch) CRITICAL: Added IS NULL guard for last_accessed_at (test had it, prod didn't) MAJOR: Replaced (window as any).__graphReheat with proper global type declaration Found by comprehensive-code-review Dim 11 (Reality Check) + Dim 15 (Honesty Audit) Co-Authored-By: Claude <noreply@anthropic.com>
- SettingsTab: setLocale(value as any) → as Locale (proper type)
- SettingsTab: llm: any → { provider, model?, apiKey? } (typed)
- api.ts: ConfigData capabilities.llm: any → LlmConfig interface
- api.ts: fetchLessons (result as any).entities → proper cast
Zero `as any` remaining in dashboard/src/
Co-Authored-By: Claude <noreply@anthropic.com>
P2-1: Use SQLite datetime() for timestamp comparison instead of JS toISOString() — avoids format mismatch on boundary dates P2-2: Graph hit-testing now skips hidden nodes (type filter + ego mode) — prevents tooltip/click on invisible nodes P2-3: Coverage percentages use full type distribution total as denominator, not just top-8 slice — fixes inflated percentages Found by Codex gpt-5.4 code review Co-Authored-By: Claude <noreply@anthropic.com>
- New /v1/patterns endpoint: work schedule, tool preferences, focus areas, workflow metrics, strengths, learning areas - New memesh_user_patterns MCP tool (8th tool): returns patterns as markdown for AI agent context - Dashboard "Your Patterns" section with 24h heatmap, tool tags, workflow stats, strengths/learning split - i18n: 11 patterns.* keys across all 11 locales - Updated schema-export.ts + fixed test count (5 → 6 tools) Co-Authored-By: Claude <noreply@anthropic.com>
- Extract computePatterns() to src/core/patterns.ts (DRY fix) - Both /v1/patterns and MCP user_patterns now share same logic - Consistent SQL ordering: ORDER BY hour for hours, ORDER BY dayNum for days - Always include dayNum in day distribution across both consumers - AnalyticsTab: symmetric .catch(() => null) on all API calls - Render stats/analytics sections independently when one fails - New tests/core/patterns.test.ts (5 tests) - Docs: 7->8 MCP tools, add user_patterns documentation - Smoke test: add dist/core/patterns.js to required files
P1: Workflow queries now search both session_keypoint AND session-insight (hooks use session-insight, not session_keypoint — metrics were always 0) P2: Added session-insight to AUTO_TYPES exclusion list (prevents synthetic entities from appearing in focus/strengths) P2: Work schedule uses localtime modifier for strftime (was UTC — peak hours shifted by timezone offset for non-UTC users) Found by Codex gpt-5.4 review Co-Authored-By: Claude <noreply@anthropic.com>
…ble deps - SQL: inline datetime() as SQL literal instead of JS string interpolation - Headers: X-Content-Type-Options, X-Frame-Options, Referrer-Policy - Deps: npm audit fix for known CVEs, override protobufjs>=7.5.5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
computePatterns()in src/core/patterns.ts,/v1/patternsendpoint,memesh_user_patternsMCP tool (8th tool), dashboard "Your Patterns" sectionTest plan
🤖 Generated with Claude Code