[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CSNXPQ9GFDNFPJY58S9FSD":3,"skill-same:01M6CSNXPQ9GFDNFPJY58S9FSD":55},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":25,"linkOnly":26,"markdownContent":27,"markdownBody":28,"frontMatter":29,"refName":33,"commitSha":34,"skillDirectory":35,"forksCount":36,"repositoryHtmlUrl":37,"repositoryHomepageUrl":37,"ownerHtmlUrl":38,"ownerBlogUrl":6,"ownerDescription":39,"updatedAt":40,"install":41,"resources":54},"01M6CSNXPQ9GFDNFPJY58S9FSD","conversation-memory",null,"Persistent memory systems for LLM conversations including short-term, long-term, and entity-based memory","Sam-06060\u002Fjarvis-assistant","Sam-06060","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F208600848?v=4","01M6CRKT7C7FXD21V6HXF293S0","Samson Frank Ganta","01M6CRKTBEKYFD8YX5Z1GT99EE",6,"Apache-2.0","https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant\u002Fblob\u002Fmain\u002Fmodules\u002Fagent_skills\u002Fawesome-skills\u002Fplaybooks\u002Fconversation-memory\u002FSKILL.md",[],[19,20,21,22,23,24],"memory","conversation memory","conversation","apache","memory systems","short","2026-11-10 10:12:30",false,"---\nname: conversation-memory\ndescription: Persistent memory systems for LLM conversations including\n  short-term, long-term, and entity-based memory\nrisk: unknown\nsource: vibeship-spawner-skills (Apache 2.0)\ndate_added: 2026-02-27\n---\n\n# Conversation Memory\n\nPersistent memory systems for LLM conversations including short-term, long-term, and entity-based memory\n\n## Capabilities\n\n- short-term-memory\n- long-term-memory\n- entity-memory\n- memory-persistence\n- memory-retrieval\n- memory-consolidation\n\n## Prerequisites\n\n- Knowledge: LLM conversation patterns, Database basics, Key-value stores\n- Skills_recommended: context-window-management, rag-implementation\n\n## Scope\n\n- Does_not_cover: Knowledge graph construction, Semantic search implementation, Database administration\n- Boundaries: Focus is memory patterns for LLMs, Covers storage and retrieval strategies\n\n## Ecosystem\n\n### Primary_tools\n\n- Mem0 - Memory layer for AI applications\n- LangChain Memory - Memory utilities in LangChain\n- Redis - In-memory data store for session memory\n\n## Patterns\n\n### Tiered Memory System\n\nDifferent memory tiers for different purposes\n\n**When to use**: Building any conversational AI\n\ninterface MemorySystem {\n    \u002F\u002F Buffer: Current conversation (in context)\n    buffer: ConversationBuffer;\n\n    \u002F\u002F Short-term: Recent interactions (session)\n    shortTerm: ShortTermMemory;\n\n    \u002F\u002F Long-term: Persistent across sessions\n    longTerm: LongTermMemory;\n\n    \u002F\u002F Entity: Facts about people, places, things\n    entity: EntityMemory;\n}\n\nclass TieredMemory implements MemorySystem {\n    async addMessage(message: Message): Promise\u003Cvoid> {\n        \u002F\u002F Always add to buffer\n        this.buffer.add(message);\n\n        \u002F\u002F Extract entities\n        const entities = await extractEntities(message);\n        for (const entity of entities) {\n            await this.entity.upsert(entity);\n        }\n\n        \u002F\u002F Check for memorable content\n        if (await isMemoryWorthy(message)) {\n            await this.shortTerm.add({\n                content: message.content,\n                timestamp: Date.now(),\n                importance: await scoreImportance(message)\n            });\n        }\n    }\n\n    async consolidate(): Promise\u003Cvoid> {\n        \u002F\u002F Move important short-term to long-term\n        const memories = await this.shortTerm.getOld(24 * 60 * 60 * 1000);\n        for (const memory of memories) {\n            if (memory.importance > 0.7 || memory.referenced > 2) {\n                await this.longTerm.add(memory);\n            }\n            await this.shortTerm.remove(memory.id);\n        }\n    }\n\n    async buildContext(query: string): Promise\u003Cstring> {\n        const parts: string[] = [];\n\n        \u002F\u002F Relevant long-term memories\n        const longTermRelevant = await this.longTerm.search(query, 3);\n        if (longTermRelevant.length) {\n            parts.push('## Relevant Memories\\n' +\n                longTermRelevant.map(m => `- ${m.content}`).join('\\n'));\n        }\n\n        \u002F\u002F Relevant entities\n        const entities = await this.entity.getRelevant(query);\n        if (entities.length) {\n            parts.push('## Known Entities\\n' +\n                entities.map(e => `- ${e.name}: ${e.facts.join(', ')}`).join('\\n'));\n        }\n\n        \u002F\u002F Recent conversation\n        const recent = this.buffer.getRecent(10);\n        parts.push('## Recent Conversation\\n' + formatMessages(recent));\n\n        return parts.join('\\n\\n');\n    }\n}\n\n### Entity Memory\n\nStore and update facts about entities\n\n**When to use**: Need to remember details about people, places, things\n\ninterface Entity {\n    id: string;\n    name: string;\n    type: 'person' | 'place' | 'thing' | 'concept';\n    facts: Fact[];\n    lastMentioned: number;\n    mentionCount: number;\n}\n\ninterface Fact {\n    content: string;\n    confidence: number;\n    source: string;  \u002F\u002F Which message this came from\n    timestamp: number;\n}\n\nclass EntityMemory {\n    async extractAndStore(message: Message): Promise\u003Cvoid> {\n        \u002F\u002F Use LLM to extract entities and facts\n        const extraction = await llm.complete(`\n            Extract entities and facts from this message.\n            Return JSON: { \"entities\": [\n                { \"name\": \"...\", \"type\": \"...\", \"facts\": [\"...\"] }\n            ]}\n\n            Message: \"${message.content}\"\n        `);\n\n        const { entities } = JSON.parse(extraction);\n        for (const entity of entities) {\n            await this.upsert(entity, message.id);\n        }\n    }\n\n    async upsert(entity: ExtractedEntity, sourceId: string): Promise\u003Cvoid> {\n        const existing = await this.store.get(entity.name.toLowerCase());\n\n        if (existing) {\n            \u002F\u002F Merge facts, avoiding duplicates\n            for (const fact of entity.facts) {\n                if (!this.hasSimilarFact(existing.facts, fact)) {\n                    existing.facts.push({\n                        content: fact,\n                        confidence: 0.9,\n                        source: sourceId,\n                        timestamp: Date.now()\n                    });\n                }\n            }\n            existing.lastMentioned = Date.now();\n            existing.mentionCount++;\n            await this.store.set(existing.id, existing);\n        } else {\n            \u002F\u002F Create new entity\n            await this.store.set(entity.name.toLowerCase(), {\n                id: generateId(),\n                name: entity.name,\n                type: entity.type,\n                facts: entity.facts.map(f => ({\n                    content: f,\n                    confidence: 0.9,\n                    source: sourceId,\n                    timestamp: Date.now()\n                })),\n                lastMentioned: Date.now(),\n                mentionCount: 1\n            });\n        }\n    }\n}\n\n### Memory-Aware Prompting\n\nInclude relevant memories in prompts\n\n**When to use**: Making LLM calls with memory context\n\nasync function promptWithMemory(\n    query: string,\n    memory: MemorySystem,\n    systemPrompt: string\n): Promise\u003Cstring> {\n    \u002F\u002F Retrieve relevant memories\n    const relevantMemories = await memory.longTerm.search(query, 5);\n    const entities = await memory.entity.getRelevant(query);\n    const recentContext = memory.buffer.getRecent(5);\n\n    \u002F\u002F Build memory-augmented prompt\n    const prompt = `\n${systemPrompt}\n\n## User Context\n${entities.length ? `Known about user:\\n${entities.map(e =>\n    `- ${e.name}: ${e.facts.map(f => f.content).join('; ')}`\n).join('\\n')}` : ''}\n\n${relevantMemories.length ? `Relevant past interactions:\\n${relevantMemories.map(m =>\n    `- [${formatDate(m.timestamp)}] ${m.content}`\n).join('\\n')}` : ''}\n\n## Recent Conversation\n${formatMessages(recentContext)}\n\n## Current Query\n${query}\n    `.trim();\n\n    const response = await llm.complete(prompt);\n\n    \u002F\u002F Extract any new memories from response\n    await memory.addMessage({ role: 'assistant', content: response });\n\n    return response;\n}\n\n## Sharp Edges\n\n### Memory store grows unbounded, system slows\n\nSeverity: HIGH\n\nSituation: System slows over time, costs increase\n\nSymptoms:\n- Slow memory retrieval\n- High storage costs\n- Increasing latency over time\n\nWhy this breaks:\nEvery message stored as memory.\nNo cleanup or consolidation.\nRetrieval over millions of items.\n\nRecommended fix:\n\n\u002F\u002F Implement memory lifecycle management\n\nclass ManagedMemory {\n    \u002F\u002F Limits\n    private readonly SHORT_TERM_MAX = 100;\n    private readonly LONG_TERM_MAX = 10000;\n    private readonly CONSOLIDATION_INTERVAL = 24 * 60 * 60 * 1000;\n\n    async add(memory: Memory): Promise\u003Cvoid> {\n        \u002F\u002F Score importance before storing\n        const score = await this.scoreImportance(memory);\n        if (score \u003C 0.3) return;  \u002F\u002F Don't store low-importance\n\n        memory.importance = score;\n        await this.shortTerm.add(memory);\n\n        \u002F\u002F Check limits\n        await this.enforceShortTermLimit();\n    }\n\n    async enforceShortTermLimit(): Promise\u003Cvoid> {\n        const count = await this.shortTerm.count();\n        if (count > this.SHORT_TERM_MAX) {\n            \u002F\u002F Consolidate: move important to long-term, delete rest\n            const memories = await this.shortTerm.getAll();\n            memories.sort((a, b) => b.importance - a.importance);\n\n            const toKeep = memories.slice(0, this.SHORT_TERM_MAX * 0.7);\n            const toConsolidate = memories.slice(this.SHORT_TERM_MAX * 0.7);\n\n            for (const m of toConsolidate) {\n                if (m.importance > 0.7) {\n                    await this.longTerm.add(m);\n                }\n                await this.shortTerm.remove(m.id);\n            }\n        }\n    }\n\n    async scoreImportance(memory: Memory): Promise\u003Cnumber> {\n        const factors = {\n            hasUserPreference: \u002Fprefer|like|don't like|hate|love\u002Fi.test(memory.content) ? 0.3 : 0,\n            hasDecision: \u002Fdecided|chose|will do|won't do\u002Fi.test(memory.content) ? 0.3 : 0,\n            hasFactAboutUser: \u002Fmy|I am|I have|I work\u002Fi.test(memory.content) ? 0.2 : 0,\n            length: memory.content.length > 100 ? 0.1 : 0,\n            userMessage: memory.role === 'user' ? 0.1 : 0,\n        };\n\n        return Object.values(factors).reduce((a, b) => a + b, 0);\n    }\n}\n\n### Retrieved memories not relevant to current query\n\nSeverity: HIGH\n\nSituation: Memories included in context but don't help\n\nSymptoms:\n- Memories in context seem random\n- User asks about things already in memory\n- Confusion from irrelevant context\n\nWhy this breaks:\nSimple keyword matching.\nNo relevance scoring.\nIncluding all retrieved memories.\n\nRecommended fix:\n\n\u002F\u002F Intelligent memory retrieval\n\nasync function retrieveRelevant(\n    query: string,\n    memories: MemoryStore,\n    maxResults: number = 5\n): Promise\u003CMemory[]> {\n    \u002F\u002F 1. Semantic search\n    const candidates = await memories.semanticSearch(query, maxResults * 3);\n\n    \u002F\u002F 2. Score relevance with context\n    const scored = await Promise.all(candidates.map(async (m) => {\n        const relevanceScore = await llm.complete(`\n            Rate 0-1 how relevant this memory is to the query.\n            Query: \"${query}\"\n            Memory: \"${m.content}\"\n            Return just the number.\n        `);\n        return { ...m, relevance: parseFloat(relevanceScore) };\n    }));\n\n    \u002F\u002F 3. Filter low relevance\n    const relevant = scored.filter(m => m.relevance > 0.5);\n\n    \u002F\u002F 4. Sort and limit\n    return relevant\n        .sort((a, b) => b.relevance - a.relevance)\n        .slice(0, maxResults);\n}\n\n### Memories from one user accessible to another\n\nSeverity: CRITICAL\n\nSituation: User sees information from another user's sessions\n\nSymptoms:\n- User sees other user's information\n- Privacy complaints\n- Compliance violations\n\nWhy this breaks:\nNo user isolation in memory store.\nShared memory namespace.\nCross-user retrieval.\n\nRecommended fix:\n\n\u002F\u002F Strict user isolation in memory\n\nclass IsolatedMemory {\n    private getKey(userId: string, memoryId: string): string {\n        \u002F\u002F Namespace all keys by user\n        return `user:${userId}:memory:${memoryId}`;\n    }\n\n    async add(userId: string, memory: Memory): Promise\u003Cvoid> {\n        \u002F\u002F Validate userId is authenticated\n        if (!isValidUserId(userId)) {\n            throw new Error('Invalid user ID');\n        }\n\n        const key = this.getKey(userId, memory.id);\n        memory.userId = userId;  \u002F\u002F Tag with user\n        await this.store.set(key, memory);\n    }\n\n    async search(userId: string, query: string): Promise\u003CMemory[]> {\n        \u002F\u002F CRITICAL: Filter by user in query\n        return await this.store.search({\n            query,\n            filter: { userId: userId },  \u002F\u002F Mandatory filter\n            limit: 10\n        });\n    }\n\n    async delete(userId: string, memoryId: string): Promise\u003Cvoid> {\n        const memory = await this.get(userId, memoryId);\n        \u002F\u002F Verify ownership before delete\n        if (memory.userId !== userId) {\n            throw new Error('Access denied');\n        }\n        await this.store.delete(this.getKey(userId, memoryId));\n    }\n\n    \u002F\u002F User data export (GDPR compliance)\n    async exportUserData(userId: string): Promise\u003CMemory[]> {\n        return await this.store.getAll({ userId });\n    }\n\n    \u002F\u002F User data deletion (GDPR compliance)\n    async deleteUserData(userId: string): Promise\u003Cvoid> {\n        const memories = await this.exportUserData(userId);\n        for (const m of memories) {\n            await this.store.delete(this.getKey(userId, m.id));\n        }\n    }\n}\n\n## Validation Checks\n\n### No User Isolation in Memory\n\nSeverity: CRITICAL\n\nMessage: Memory operations without user isolation. Privacy vulnerability.\n\nFix action: Add userId to all memory operations, filter by user on retrieval\n\n### No Importance Filtering\n\nSeverity: WARNING\n\nMessage: Storing memories without importance filtering. May cause memory explosion.\n\nFix action: Score importance before storing, filter low-importance content\n\n### Memory Storage Without Retrieval\n\nSeverity: WARNING\n\nMessage: Storing memories but no retrieval logic. Memories won't be used.\n\nFix action: Implement memory retrieval and include in prompts\n\n### No Memory Cleanup\n\nSeverity: INFO\n\nMessage: No memory cleanup mechanism. Storage will grow unbounded.\n\nFix action: Implement consolidation and cleanup based on age\u002Fimportance\n\n## Collaboration\n\n### Delegation Triggers\n\n- context window|token -> context-window-management (Need context optimization)\n- rag|retrieval|vector -> rag-implementation (Need retrieval system)\n- cache|caching -> prompt-caching (Need caching strategies)\n\n### Complete Memory System\n\nSkills: conversation-memory, context-window-management, rag-implementation\n\nWorkflow:\n\n```\n1. Design memory tiers\n2. Implement storage and retrieval\n3. Integrate with context management\n4. Add consolidation and cleanup\n```\n\n## Related Skills\n\nWorks well with: `context-window-management`, `rag-implementation`, `prompt-caching`, `llm-npc-dialogue`\n\n## When to Use\n\n- User mentions or implies: conversation memory\n- User mentions or implies: remember\n- User mentions or implies: memory persistence\n- User mentions or implies: long-term memory\n- User mentions or implies: chat history\n","# Conversation Memory\n\nPersistent memory systems for LLM conversations including short-term, long-term, and entity-based memory\n\n## Capabilities\n\n- short-term-memory\n- long-term-memory\n- entity-memory\n- memory-persistence\n- memory-retrieval\n- memory-consolidation\n\n## Prerequisites\n\n- Knowledge: LLM conversation patterns, Database basics, Key-value stores\n- Skills_recommended: context-window-management, rag-implementation\n\n## Scope\n\n- Does_not_cover: Knowledge graph construction, Semantic search implementation, Database administration\n- Boundaries: Focus is memory patterns for LLMs, Covers storage and retrieval strategies\n\n## Ecosystem\n\n### Primary_tools\n\n- Mem0 - Memory layer for AI applications\n- LangChain Memory - Memory utilities in LangChain\n- Redis - In-memory data store for session memory\n\n## Patterns\n\n### Tiered Memory System\n\nDifferent memory tiers for different purposes\n\n**When to use**: Building any conversational AI\n\ninterface MemorySystem {\n    \u002F\u002F Buffer: Current conversation (in context)\n    buffer: ConversationBuffer;\n\n    \u002F\u002F Short-term: Recent interactions (session)\n    shortTerm: ShortTermMemory;\n\n    \u002F\u002F Long-term: Persistent across sessions\n    longTerm: LongTermMemory;\n\n    \u002F\u002F Entity: Facts about people, places, things\n    entity: EntityMemory;\n}\n\nclass TieredMemory implements MemorySystem {\n    async addMessage(message: Message): Promise\u003Cvoid> {\n        \u002F\u002F Always add to buffer\n        this.buffer.add(message);\n\n        \u002F\u002F Extract entities\n        const entities = await extractEntities(message);\n        for (const entity of entities) {\n            await this.entity.upsert(entity);\n        }\n\n        \u002F\u002F Check for memorable content\n        if (await isMemoryWorthy(message)) {\n            await this.shortTerm.add({\n                content: message.content,\n                timestamp: Date.now(),\n                importance: await scoreImportance(message)\n            });\n        }\n    }\n\n    async consolidate(): Promise\u003Cvoid> {\n        \u002F\u002F Move important short-term to long-term\n        const memories = await this.shortTerm.getOld(24 * 60 * 60 * 1000);\n        for (const memory of memories) {\n            if (memory.importance > 0.7 || memory.referenced > 2) {\n                await this.longTerm.add(memory);\n            }\n            await this.shortTerm.remove(memory.id);\n        }\n    }\n\n    async buildContext(query: string): Promise\u003Cstring> {\n        const parts: string[] = [];\n\n        \u002F\u002F Relevant long-term memories\n        const longTermRelevant = await this.longTerm.search(query, 3);\n        if (longTermRelevant.length) {\n            parts.push('## Relevant Memories\\n' +\n                longTermRelevant.map(m => `- ${m.content}`).join('\\n'));\n        }\n\n        \u002F\u002F Relevant entities\n        const entities = await this.entity.getRelevant(query);\n        if (entities.length) {\n            parts.push('## Known Entities\\n' +\n                entities.map(e => `- ${e.name}: ${e.facts.join(', ')}`).join('\\n'));\n        }\n\n        \u002F\u002F Recent conversation\n        const recent = this.buffer.getRecent(10);\n        parts.push('## Recent Conversation\\n' + formatMessages(recent));\n\n        return parts.join('\\n\\n');\n    }\n}\n\n### Entity Memory\n\nStore and update facts about entities\n\n**When to use**: Need to remember details about people, places, things\n\ninterface Entity {\n    id: string;\n    name: string;\n    type: 'person' | 'place' | 'thing' | 'concept';\n    facts: Fact[];\n    lastMentioned: number;\n    mentionCount: number;\n}\n\ninterface Fact {\n    content: string;\n    confidence: number;\n    source: string;  \u002F\u002F Which message this came from\n    timestamp: number;\n}\n\nclass EntityMemory {\n    async extractAndStore(message: Message): Promise\u003Cvoid> {\n        \u002F\u002F Use LLM to extract entities and facts\n        const extraction = await llm.complete(`\n            Extract entities and facts from this message.\n            Return JSON: { \"entities\": [\n                { \"name\": \"...\", \"type\": \"...\", \"facts\": [\"...\"] }\n            ]}\n\n            Message: \"${message.content}\"\n        `);\n\n        const { entities } = JSON.parse(extraction);\n        for (const entity of entities) {\n            await this.upsert(entity, message.id);\n        }\n    }\n\n    async upsert(entity: ExtractedEntity, sourceId: string): Promise\u003Cvoid> {\n        const existing = await this.store.get(entity.name.toLowerCase());\n\n        if (existing) {\n            \u002F\u002F Merge facts, avoiding duplicates\n            for (const fact of entity.facts) {\n                if (!this.hasSimilarFact(existing.facts, fact)) {\n                    existing.facts.push({\n                        content: fact,\n                        confidence: 0.9,\n                        source: sourceId,\n                        timestamp: Date.now()\n                    });\n                }\n            }\n            existing.lastMentioned = Date.now();\n            existing.mentionCount++;\n            await this.store.set(existing.id, existing);\n        } else {\n            \u002F\u002F Create new entity\n            await this.store.set(entity.name.toLowerCase(), {\n                id: generateId(),\n                name: entity.name,\n                type: entity.type,\n                facts: entity.facts.map(f => ({\n                    content: f,\n                    confidence: 0.9,\n                    source: sourceId,\n                    timestamp: Date.now()\n                })),\n                lastMentioned: Date.now(),\n                mentionCount: 1\n            });\n        }\n    }\n}\n\n### Memory-Aware Prompting\n\nInclude relevant memories in prompts\n\n**When to use**: Making LLM calls with memory context\n\nasync function promptWithMemory(\n    query: string,\n    memory: MemorySystem,\n    systemPrompt: string\n): Promise\u003Cstring> {\n    \u002F\u002F Retrieve relevant memories\n    const relevantMemories = await memory.longTerm.search(query, 5);\n    const entities = await memory.entity.getRelevant(query);\n    const recentContext = memory.buffer.getRecent(5);\n\n    \u002F\u002F Build memory-augmented prompt\n    const prompt = `\n${systemPrompt}\n\n## User Context\n${entities.length ? `Known about user:\\n${entities.map(e =>\n    `- ${e.name}: ${e.facts.map(f => f.content).join('; ')}`\n).join('\\n')}` : ''}\n\n${relevantMemories.length ? `Relevant past interactions:\\n${relevantMemories.map(m =>\n    `- [${formatDate(m.timestamp)}] ${m.content}`\n).join('\\n')}` : ''}\n\n## Recent Conversation\n${formatMessages(recentContext)}\n\n## Current Query\n${query}\n    `.trim();\n\n    const response = await llm.complete(prompt);\n\n    \u002F\u002F Extract any new memories from response\n    await memory.addMessage({ role: 'assistant', content: response });\n\n    return response;\n}\n\n## Sharp Edges\n\n### Memory store grows unbounded, system slows\n\nSeverity: HIGH\n\nSituation: System slows over time, costs increase\n\nSymptoms:\n- Slow memory retrieval\n- High storage costs\n- Increasing latency over time\n\nWhy this breaks:\nEvery message stored as memory.\nNo cleanup or consolidation.\nRetrieval over millions of items.\n\nRecommended fix:\n\n\u002F\u002F Implement memory lifecycle management\n\nclass ManagedMemory {\n    \u002F\u002F Limits\n    private readonly SHORT_TERM_MAX = 100;\n    private readonly LONG_TERM_MAX = 10000;\n    private readonly CONSOLIDATION_INTERVAL = 24 * 60 * 60 * 1000;\n\n    async add(memory: Memory): Promise\u003Cvoid> {\n        \u002F\u002F Score importance before storing\n        const score = await this.scoreImportance(memory);\n        if (score \u003C 0.3) return;  \u002F\u002F Don't store low-importance\n\n        memory.importance = score;\n        await this.shortTerm.add(memory);\n\n        \u002F\u002F Check limits\n        await this.enforceShortTermLimit();\n    }\n\n    async enforceShortTermLimit(): Promise\u003Cvoid> {\n        const count = await this.shortTerm.count();\n        if (count > this.SHORT_TERM_MAX) {\n            \u002F\u002F Consolidate: move important to long-term, delete rest\n            const memories = await this.shortTerm.getAll();\n            memories.sort((a, b) => b.importance - a.importance);\n\n            const toKeep = memories.slice(0, this.SHORT_TERM_MAX * 0.7);\n            const toConsolidate = memories.slice(this.SHORT_TERM_MAX * 0.7);\n\n            for (const m of toConsolidate) {\n                if (m.importance > 0.7) {\n                    await this.longTerm.add(m);\n                }\n                await this.shortTerm.remove(m.id);\n            }\n        }\n    }\n\n    async scoreImportance(memory: Memory): Promise\u003Cnumber> {\n        const factors = {\n            hasUserPreference: \u002Fprefer|like|don't like|hate|love\u002Fi.test(memory.content) ? 0.3 : 0,\n            hasDecision: \u002Fdecided|chose|will do|won't do\u002Fi.test(memory.content) ? 0.3 : 0,\n            hasFactAboutUser: \u002Fmy|I am|I have|I work\u002Fi.test(memory.content) ? 0.2 : 0,\n            length: memory.content.length > 100 ? 0.1 : 0,\n            userMessage: memory.role === 'user' ? 0.1 : 0,\n        };\n\n        return Object.values(factors).reduce((a, b) => a + b, 0);\n    }\n}\n\n### Retrieved memories not relevant to current query\n\nSeverity: HIGH\n\nSituation: Memories included in context but don't help\n\nSymptoms:\n- Memories in context seem random\n- User asks about things already in memory\n- Confusion from irrelevant context\n\nWhy this breaks:\nSimple keyword matching.\nNo relevance scoring.\nIncluding all retrieved memories.\n\nRecommended fix:\n\n\u002F\u002F Intelligent memory retrieval\n\nasync function retrieveRelevant(\n    query: string,\n    memories: MemoryStore,\n    maxResults: number = 5\n): Promise\u003CMemory[]> {\n    \u002F\u002F 1. Semantic search\n    const candidates = await memories.semanticSearch(query, maxResults * 3);\n\n    \u002F\u002F 2. Score relevance with context\n    const scored = await Promise.all(candidates.map(async (m) => {\n        const relevanceScore = await llm.complete(`\n            Rate 0-1 how relevant this memory is to the query.\n            Query: \"${query}\"\n            Memory: \"${m.content}\"\n            Return just the number.\n        `);\n        return { ...m, relevance: parseFloat(relevanceScore) };\n    }));\n\n    \u002F\u002F 3. Filter low relevance\n    const relevant = scored.filter(m => m.relevance > 0.5);\n\n    \u002F\u002F 4. Sort and limit\n    return relevant\n        .sort((a, b) => b.relevance - a.relevance)\n        .slice(0, maxResults);\n}\n\n### Memories from one user accessible to another\n\nSeverity: CRITICAL\n\nSituation: User sees information from another user's sessions\n\nSymptoms:\n- User sees other user's information\n- Privacy complaints\n- Compliance violations\n\nWhy this breaks:\nNo user isolation in memory store.\nShared memory namespace.\nCross-user retrieval.\n\nRecommended fix:\n\n\u002F\u002F Strict user isolation in memory\n\nclass IsolatedMemory {\n    private getKey(userId: string, memoryId: string): string {\n        \u002F\u002F Namespace all keys by user\n        return `user:${userId}:memory:${memoryId}`;\n    }\n\n    async add(userId: string, memory: Memory): Promise\u003Cvoid> {\n        \u002F\u002F Validate userId is authenticated\n        if (!isValidUserId(userId)) {\n            throw new Error('Invalid user ID');\n        }\n\n        const key = this.getKey(userId, memory.id);\n        memory.userId = userId;  \u002F\u002F Tag with user\n        await this.store.set(key, memory);\n    }\n\n    async search(userId: string, query: string): Promise\u003CMemory[]> {\n        \u002F\u002F CRITICAL: Filter by user in query\n        return await this.store.search({\n            query,\n            filter: { userId: userId },  \u002F\u002F Mandatory filter\n            limit: 10\n        });\n    }\n\n    async delete(userId: string, memoryId: string): Promise\u003Cvoid> {\n        const memory = await this.get(userId, memoryId);\n        \u002F\u002F Verify ownership before delete\n        if (memory.userId !== userId) {\n            throw new Error('Access denied');\n        }\n        await this.store.delete(this.getKey(userId, memoryId));\n    }\n\n    \u002F\u002F User data export (GDPR compliance)\n    async exportUserData(userId: string): Promise\u003CMemory[]> {\n        return await this.store.getAll({ userId });\n    }\n\n    \u002F\u002F User data deletion (GDPR compliance)\n    async deleteUserData(userId: string): Promise\u003Cvoid> {\n        const memories = await this.exportUserData(userId);\n        for (const m of memories) {\n            await this.store.delete(this.getKey(userId, m.id));\n        }\n    }\n}\n\n## Validation Checks\n\n### No User Isolation in Memory\n\nSeverity: CRITICAL\n\nMessage: Memory operations without user isolation. Privacy vulnerability.\n\nFix action: Add userId to all memory operations, filter by user on retrieval\n\n### No Importance Filtering\n\nSeverity: WARNING\n\nMessage: Storing memories without importance filtering. May cause memory explosion.\n\nFix action: Score importance before storing, filter low-importance content\n\n### Memory Storage Without Retrieval\n\nSeverity: WARNING\n\nMessage: Storing memories but no retrieval logic. Memories won't be used.\n\nFix action: Implement memory retrieval and include in prompts\n\n### No Memory Cleanup\n\nSeverity: INFO\n\nMessage: No memory cleanup mechanism. Storage will grow unbounded.\n\nFix action: Implement consolidation and cleanup based on age\u002Fimportance\n\n## Collaboration\n\n### Delegation Triggers\n\n- context window|token -> context-window-management (Need context optimization)\n- rag|retrieval|vector -> rag-implementation (Need retrieval system)\n- cache|caching -> prompt-caching (Need caching strategies)\n\n### Complete Memory System\n\nSkills: conversation-memory, context-window-management, rag-implementation\n\nWorkflow:\n\n```\n1. Design memory tiers\n2. Implement storage and retrieval\n3. Integrate with context management\n4. Add consolidation and cleanup\n```\n\n## Related Skills\n\nWorks well with: `context-window-management`, `rag-implementation`, `prompt-caching`, `llm-npc-dialogue`\n\n## When to Use\n\n- User mentions or implies: conversation memory\n- User mentions or implies: remember\n- User mentions or implies: memory persistence\n- User mentions or implies: long-term memory\n- User mentions or implies: chat history\n",{"name":5,"risk":30,"source":31,"date_added":32,"description":7},"unknown","vibeship-spawner-skills (Apache 2.0)",1772150400000,"main","a50a3aa6b39fb0e1b7db88bef1bfc9c93606e126","modules\u002Fagent_skills\u002Fawesome-skills\u002Fplaybooks\u002Fconversation-memory",0,"https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant","https:\u002F\u002Fgithub.com\u002FSam-06060","Mobile Application Developer | Kotlin | Flutter, KMP, Swfit, Android,Swift UI | Building at Saar It Resources | Creator of Jarvis (AI Assistant)","2026-06-23 05:13:38",{"source":8,"skillName":5,"commands":42,"prompt":52,"zipAvailable":53},[43,46,49],{"tool":44,"command":45},"npx","npx skills add Sam-06060\u002Fjarvis-assistant --skill conversation-memory",{"tool":47,"command":48},"bunx","bunx skills add Sam-06060\u002Fjarvis-assistant --skill conversation-memory",{"tool":50,"command":51},"pnpm","pnpm dlx skills add Sam-06060\u002Fjarvis-assistant --skill conversation-memory","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant\u002Fblob\u002Fmain\u002Fmodules\u002Fagent_skills\u002Fawesome-skills\u002Fplaybooks\u002Fconversation-memory\u002FSKILL.md",true,[],[56,69,86,113,132,159],{"skillNo":57,"name":58,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":59,"categories":60,"keywords":66,"publishedAt":25},"01M6GDRVS6FXX3ESH0C9DW01C0","test_skill","https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant\u002Fblob\u002Fmain\u002Fscratch\u002Ftest_skill\u002FSKILL.md",[61],{"categoryNo":62,"categoryName":63,"taxonomyType":64,"taxonomyTypeDesc":65},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[67,68],"Test Skill","test",{"skillNo":70,"name":71,"nameZh":6,"description":72,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":73,"categories":74,"keywords":75,"publishedAt":25},"01M6GDRQ40HX22MA6XWC31RHHK","zustand-store-ts","Create Zustand stores following established patterns with proper TypeScript types and middleware.","https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant\u002Fblob\u002Fmain\u002Fmodules\u002Fagent_skills\u002Fawesome-skills\u002Fplaybooks\u002Fzustand-store-ts\u002FSKILL.md",[],[76,77,78,79,80,81,82,83,84,85],"zustand store ts","zustand","store","with","types","middleware","patterns","community","create","typescript",{"skillNo":87,"name":88,"nameZh":6,"description":89,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":90,"categories":91,"keywords":95,"publishedAt":25},"01M6GDRKEA0WE670SPFWX5GKCN","zoom-automation","Automate Zoom meeting creation, management, recordings, webinars, and participant tracking via Rube MCP (Composio). Always search tools first for current schemas.","https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant\u002Fblob\u002Fmain\u002Fmodules\u002Fagent_skills\u002Fawesome-skills\u002Fplaybooks\u002Fzoom-automation\u002FSKILL.md",[92],{"categoryNo":93,"categoryName":94,"taxonomyType":64,"taxonomyTypeDesc":65},"01JBSEEDCAT000000000000023","Skill与智能体开发",[96,97,98,99,100,101,102,103,104,105,106,107,108,109,83,110,111,112],"automation","zoom automation","zoom","first","Tools","search","MCP","via","meeting","automate","critical","creation","webinars","composio","recordings","management","tracking",{"skillNo":114,"name":115,"nameZh":6,"description":116,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":117,"categories":118,"keywords":120,"publishedAt":25},"01M6GDRFS1452PC71JQ38S24HR","zoho-crm-automation","Automate Zoho CRM tasks via Rube MCP (Composio): create\u002Fupdate records, search contacts, manage leads, and convert leads. Always search tools first for current schemas.","https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant\u002Fblob\u002Fmain\u002Fmodules\u002Fagent_skills\u002Fawesome-skills\u002Fplaybooks\u002Fzoho-crm-automation\u002FSKILL.md",[119],{"categoryNo":93,"categoryName":94,"taxonomyType":64,"taxonomyTypeDesc":65},[121,96,122,123,124,125,126,83,101,127,109,128,106,105,100,129,84,130,102,131],"crm automation","zoho crm","crm","zoho crm automation","zoho","leads","contacts","records","update","tasks","manage",{"skillNo":133,"name":134,"nameZh":6,"description":135,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":136,"categories":137,"keywords":141,"publishedAt":25},"01M6GDRCKQBAVTGHX5XBH26KPZ","zod-validation-expert","Expert in Zod — TypeScript-first schema validation. Covers parsing, custom errors, refinements, type inference, and integration with React Hook Form, Next.js, and tRPC.","https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant\u002Fblob\u002Fmain\u002Fmodules\u002Fagent_skills\u002Fawesome-skills\u002Fplaybooks\u002Fzod-validation-expert\u002FSKILL.md",[138],{"categoryNo":139,"categoryName":140,"taxonomyType":64,"taxonomyTypeDesc":65},"01JBSEEDCAT000000000000009","前端开发",[142,143,144,145,146,85,147,148,149,150,151,152,79,153,154,155,156,83,157,158],"expert","zod","zod validation expert","validation","react","safe","parsing","errors","schema validation","react hook form","hook","trpc","form","type","next","schema","Next.js",{"skillNo":160,"name":161,"nameZh":6,"description":162,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":163,"categories":164,"keywords":166,"publishedAt":25},"01M6GDR658B08K4MY0RWD4A6EH","zeroize-audit","Detects missing zeroization of sensitive data in source code and identifies zeroization removed by compiler optimizations, with assembly-level analysis, and control-flow verification. Use for auditing C\u002FC++\u002FRust code handling secrets, keys, passwords, or other sensitive data.","https:\u002F\u002Fgithub.com\u002FSam-06060\u002Fjarvis-assistant\u002Fblob\u002Fmain\u002Fmodules\u002Fagent_skills\u002Fawesome-skills\u002Fplaybooks\u002Fzeroize-audit\u002FSKILL.md",[165],{"categoryNo":93,"categoryName":94,"taxonomyType":64,"taxonomyTypeDesc":65},[167,168,169,170,171,172,173,174,83,175,176,177,178,179,180,181,182,183,184,102],"zeroize audit","audit","write","passwords","get","project","c++","activate","assembly","read","Bash","secrets","analysis","data","flow","verification","code","rust"]