17 KiB
Memory Architecture: Chat + User Consolidation Implementation Plan
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Introduzir uma arquitetura de memória segura e incremental que extraia memórias estruturadas com o modelo local models/embedding/gemma-3-270m-it-Q8_0.gguf, separe memória de chat e memória de usuário, consolide memórias entre chats sem duplicação e prepare o terreno para uso dinâmico em prompts futuros.
Architecture: A implementação será dividida em duas pipelines desacopladas: (1) extração de memória de chat a partir de mensagens concluídas em um chat específico; (2) consolidação de memória de usuário a partir das memórias de chat já processadas. Para evitar quebrar o fluxo atual, a extração será feita em background, com schema novo e compatibilidade retroativa com user_memories. A primeira fase não altera o prompt principal do chat; apenas cria, valida, deduplica e persiste a memória corretamente.
Tech Stack: React/TypeScript, Tauri frontend, SQLite local (db.ts), API compatível OpenAI do runtime local, modelo GGUF local gemma-3-270m-it-Q8_0.gguf, Vitest.
Princípios de segurança desta implementação
- Não quebrar o chat atual: memória nova roda em background e falha silenciosamente.
- Não misturar memória bruta com prompt principal ainda: primeiro persistimos corretamente, depois conectamos ao prompt.
- Não usar mensagens inteiras como memória final: só fatos estruturados, classificados e deduplicados.
- Separação explícita:
chat memories= fatos extraídos de um chat específicouser memories= fatos consolidados a partir de vários chats
- Idempotência: nunca reprocessar o mesmo insumo sem necessidade.
- Deduplicação conservadora: primeiro por chave/categoria/valor normalizado; sem embeddings sofisticados nesta fase.
- Modelo único para extração/classificação: usar
gemma-3-270m-it-Q8_0.ggufcomo extractor/classifier local.
Resultado esperado desta fase
Ao final desta implementação:
- cada chat poderá gerar memórias estruturadas próprias;
- memórias de usuário serão derivadas das memórias de chat já consolidadas;
- duplicatas não serão reinseridas;
- memórias terão tipo/classificação/confiança/origem;
- o sistema estará pronto para usar essas memórias em prompts dinâmicos futuros, sem ainda acoplar tudo ao chat principal.
Modelo de dados recomendado
Tabela 1: chat_memories
Representa fatos persistidos derivados de um chat.
Campos sugeridos:
id INTEGER PRIMARY KEYchat_id INTEGER NOT NULLsource_message_id INTEGER NULLmemory_key TEXT NOT NULLmemory_value TEXT NOT NULLmemory_category TEXT NOT NULLmemory_scope TEXT NOT NULL DEFAULT 'chat'confidence REAL NOT NULLevidence TEXT NULLfirst_seen_at INTEGER NOT NULLlast_seen_at INTEGER NOT NULLnormalized_value TEXT NOT NULLsuperseded_by INTEGER NULLcreated_at INTEGER NOT NULLupdated_at INTEGER NOT NULL
Categorias permitidas inicialmente:
identityprofilepreferenceinteresthabitprojectconstraintgoaltopic_patternskill
Tabela 2: user_memories_v2
Representa fatos consolidados a partir de chat_memories.
Campos sugeridos:
id INTEGER PRIMARY KEYmemory_key TEXT NOT NULLmemory_value TEXT NOT NULLmemory_category TEXT NOT NULLconfidence REAL NOT NULLnormalized_value TEXT NOT NULLsupporting_chat_memory_ids TEXT NOT NULL(JSON array)evidence_summary TEXT NULLfirst_seen_at INTEGER NOT NULLlast_seen_at INTEGER NOT NULLcreated_at INTEGER NOT NULLupdated_at INTEGER NOT NULL
Tabela 3: memory_jobs
Fila/log de processamento para idempotência.
Campos sugeridos:
id INTEGER PRIMARY KEYjob_type TEXT NOT NULL(chat_extract|user_consolidate)target_id INTEGER NOT NULLstatus TEXT NOT NULL(pending|running|done|failed)attempts INTEGER NOT NULL DEFAULT 0last_error TEXT NULLcreated_at INTEGER NOT NULLupdated_at INTEGER NOT NULL
Prompt recomendado para extração de memória de chat
Arquivo novo sugerido: tauri-app/src/prompts/memory-extraction.ts
Prompt base
You are a local memory extraction and classification engine.
Your task is to read a conversation fragment and extract ONLY durable, reusable memory items.
Return ONLY valid JSON as an array.
Each item must follow this schema:
{
"memory_key": "snake_case_key",
"memory_value": "concise factual value",
"memory_category": "identity|profile|preference|interest|habit|project|constraint|goal|topic_pattern|skill",
"confidence": 0.0,
"evidence": "short quote or short rationale",
"is_user_memory_candidate": true
}
Extraction policy:
- Extract durable facts, not temporary requests.
- Extract user preferences, likes/dislikes, recurring interests, profession, age, location, constraints, active projects, goals, skills, and patterns in what the user usually searches or asks about.
- Prefer atomic facts.
- Do not repeat equivalent items.
- If a fact is uncertain, lower confidence.
- If nothing durable exists, return [].
- Never output markdown.
Prompt adicional para consolidação de memória de usuário
You are a user memory consolidator.
Input: existing user memories + candidate chat memories.
Goal: produce ONLY new or improved user-level memories.
Rules:
- Do not repeat existing memories.
- Merge semantically equivalent facts.
- Prefer the most stable formulation.
- Keep only durable cross-chat knowledge.
- If a fact appears in multiple chats, increase confidence.
- Return ONLY valid JSON array with the same schema.
Fases de implementação
Task 1: Congelar o comportamento atual com testes de regressão
Files:
- Create:
tauri-app/src/hooks/useMemoryExtractor.test.ts - Test:
tauri-app/src/components/ChatView.test.tsx
Step 1: Escrever teste de regressão do fluxo atual Validar que, se o extractor falhar, o chat principal continua funcionando.
Step 2: Rodar teste para confirmar baseline
Run: cd tauri-app && npm test -- src/hooks/useMemoryExtractor.test.ts
Expected: FAIL inicialmente (arquivo novo).
Step 3: Criar teste mínimo de não-regressão Cobrir:
- extractor não bloqueia envio de mensagem
- erro de memória não quebra render/chat
Step 4: Rodar testes
Run: cd tauri-app && npm test -- src/hooks/useMemoryExtractor.test.ts src/components/ChatView.test.tsx
Expected: PASS
Step 5: Commit
git add tauri-app/src/hooks/useMemoryExtractor.test.ts tauri-app/src/components/ChatView.test.tsx
git commit -m "test: add memory extraction regression coverage"
Task 2: Introduzir schema novo sem remover o antigo
Files:
- Modify:
tauri-app/src/lib/db.ts - Modify:
tauri-app/src/lib/types.ts - Create:
tauri-app/src/lib/memory-types.ts - Test:
tauri-app/src/lib/db.test.ts
Step 1: Escrever testes falhos para novas tabelas Cobrir criação idempotente de:
chat_memoriesuser_memories_v2memory_jobs
Step 2: Adicionar migração aditiva
Em db.ts, usar ensureTable/ensureColumn (ou equivalente local) sem remover user_memories atual.
Step 3: Declarar tipos explícitos Criar interfaces para:
ChatMemoryUserMemoryV2MemoryJobMemoryCandidate
Step 4: Rodar testes
Run: cd tauri-app && npm test -- src/lib/db.test.ts
Expected: PASS
Step 5: Commit
git add tauri-app/src/lib/db.ts tauri-app/src/lib/types.ts tauri-app/src/lib/memory-types.ts tauri-app/src/lib/db.test.ts
git commit -m "feat: add chat and user memory schema"
Task 3: Configurar o modelo local de memória sem tocar no modelo principal
Files:
- Create:
tauri-app/src/config/memory.ts - Modify:
tauri-app/src/config/ai.tsortauri-app/src/config/ai/index.ts - Test:
tauri-app/src/features/runtime/runtime-utils.test.ts
Step 1: Escrever teste falho de resolução da configuração Configurar constante para:
MEMORY_MODEL_PATH = "models/embedding/gemma-3-270m-it-Q8_0.gguf"MEMORY_MODEL_ID = "gemma-3-270m-it-Q8_0"
Step 2: Implementar configuração dedicada A memória deve usar modelo separado do chat principal.
Step 3: Adicionar fallback seguro Se o arquivo não existir, a memória desabilita-se sem derrubar o app.
Step 4: Rodar testes
Run: cd tauri-app && npm test -- src/features/runtime/runtime-utils.test.ts
Expected: PASS
Step 5: Commit
git add tauri-app/src/config/memory.ts tauri-app/src/config/ai.ts tauri-app/src/config/ai/index.ts tauri-app/src/features/runtime/runtime-utils.test.ts
git commit -m "feat: configure dedicated local memory model"
Task 4: Implementar prompt e parser de extração estruturada
Files:
- Create:
tauri-app/src/prompts/memory-extraction.ts - Create:
tauri-app/src/lib/memory-parser.ts - Create:
tauri-app/src/lib/memory-parser.test.ts
Step 1: Escrever testes falhos para parsing de JSON robusto Cobrir:
- array JSON puro
- JSON com ruído ao redor
- array vazio
- item inválido descartado
- normalização de
memory_key - clamp de confiança
Step 2: Implementar parser minimalista Funções sugeridas:
parseMemoryCandidates(raw: string): MemoryCandidate[]normalizeMemoryCandidate(candidate): MemoryCandidate | null
Step 3: Rodar testes
Run: cd tauri-app && npm test -- src/lib/memory-parser.test.ts
Expected: PASS
Step 4: Commit
git add tauri-app/src/prompts/memory-extraction.ts tauri-app/src/lib/memory-parser.ts tauri-app/src/lib/memory-parser.test.ts
git commit -m "feat: add structured memory extraction prompt and parser"
Task 5: Extrair memórias de chat em background
Files:
- Modify:
tauri-app/src/hooks/useMemoryExtractor.ts - Create:
tauri-app/src/lib/chat-memory-repository.ts - Test:
tauri-app/src/hooks/useMemoryExtractor.test.ts
Step 1: Escrever testes falhos para pipeline de chat memory Cobrir:
- usa modelo de memória dedicado
- envia prompt de extração correto
- salva em
chat_memories - marca job/mensagem como processado
- não salva duplicata exata
Step 2: Refatorar o hook atual
O hook atual não deve mais gravar direto em user_memories.
Agora deve:
- ler mensagens recentes
- chamar o modelo de memória
- parsear candidatos
- persistir em
chat_memories - registrar job concluído
Step 3: Implementar deduplicação conservadora Deduplicar por:
chat_idmemory_keynormalized_value
Step 4: Rodar testes
Run: cd tauri-app && npm test -- src/hooks/useMemoryExtractor.test.ts
Expected: PASS
Step 5: Commit
git add tauri-app/src/hooks/useMemoryExtractor.ts tauri-app/src/lib/chat-memory-repository.ts tauri-app/src/hooks/useMemoryExtractor.test.ts
git commit -m "feat: extract chat-scoped memories with local model"
Task 6: Consolidar memórias de usuário a partir das memórias de chat
Files:
- Create:
tauri-app/src/lib/user-memory-consolidator.ts - Create:
tauri-app/src/lib/user-memory-repository.ts - Create:
tauri-app/src/lib/user-memory-consolidator.test.ts
Step 1: Escrever testes falhos da consolidação Cobrir:
- lê
chat_memoriesjá processadas - compara com
user_memories_v2 - cria apenas memórias novas
- melhora memória existente quando confiança aumenta
- não duplica fatos equivalentes
Step 2: Implementar consolidador em duas etapas Etapa A:
- selecionar candidatas recentes de
chat_memoriesEtapa B: - chamar o modelo com:
- memórias de usuário já existentes
- novas memórias de chat
- receber apenas novos fatos consolidados
Step 3: Persistir com rastreabilidade
Salvar também supporting_chat_memory_ids.
Step 4: Rodar testes
Run: cd tauri-app && npm test -- src/lib/user-memory-consolidator.test.ts
Expected: PASS
Step 5: Commit
git add tauri-app/src/lib/user-memory-consolidator.ts tauri-app/src/lib/user-memory-repository.ts tauri-app/src/lib/user-memory-consolidator.test.ts
git commit -m "feat: consolidate user memories from chat memories"
Task 7: Definir política de classificação e uso futuro em prompts
Files:
- Create:
tauri-app/src/lib/memory-prompt-context.ts - Create:
tauri-app/src/lib/memory-prompt-context.test.ts - Modify:
tauri-app/src/hooks/useMemoryExtractor.ts
Step 1: Escrever teste falho para construção de contexto dinâmico Sem injetar ainda no chat principal, criar builder que monte:
chat memory contextuser memory contextseparados e filtrados por confiança/categoria.
Step 2: Implementar builder de contexto Regras iniciais:
identity/profile/preferences/constraints/goalscom prioridade altatopic_pattern/interestslimitados por recência e confiança- sem repetir fatos equivalentes
Step 3: Rodar testes
Run: cd tauri-app && npm test -- src/lib/memory-prompt-context.test.ts
Expected: PASS
Step 4: Commit
git add tauri-app/src/lib/memory-prompt-context.ts tauri-app/src/lib/memory-prompt-context.test.ts tauri-app/src/hooks/useMemoryExtractor.ts
git commit -m "feat: prepare structured memory prompt context builder"
Task 8: Adicionar comando de consolidação segura e agendada
Files:
- Create:
tauri-app/src/lib/memory-orchestrator.ts - Modify:
tauri-app/src/components/ChatView.tsx - Test:
tauri-app/src/components/ChatView.test.tsx
Step 1: Escrever teste falho do orquestrador Cobrir:
- após resposta concluída, roda extração de chat
- consolidação de usuário roda desacoplada/debounced
- falha em qualquer etapa não afeta o chat
Step 2: Implementar orquestrador leve Fluxo:
assistant turn complete→ enqueuechat_extract- depois → enqueue
user_consolidatecom debounce maior
Step 3: Rodar testes
Run: cd tauri-app && npm test -- src/components/ChatView.test.tsx
Expected: PASS
Step 4: Commit
git add tauri-app/src/lib/memory-orchestrator.ts tauri-app/src/components/ChatView.tsx tauri-app/src/components/ChatView.test.tsx
git commit -m "feat: orchestrate chat and user memory processing safely"
Task 9: Estratégia de migração sem quebra
Files:
- Create:
docs/memory-migration-notes.md - Modify:
tauri-app/src/hooks/useMemoryExtractor.ts - Test:
tauri-app/src/lib/db.test.ts
Step 1: Definir política de coexistência
user_memoriesantiga fica preservada- nova pipeline escreve em
chat_memorieseuser_memories_v2 - nenhuma leitura crítica do app depende imediatamente da nova tabela
Step 2: Opcional: migração parcial de legado
Se necessário, criar utilitário futuro de backfill de user_memories → user_memories_v2, mas não nesta fase.
Step 3: Documentar explicitamente Descrever:
- rollback fácil
- como desligar a feature
- como validar DB localmente
Step 4: Commit
git add docs/memory-migration-notes.md tauri-app/src/hooks/useMemoryExtractor.ts tauri-app/src/lib/db.test.ts
git commit -m "docs: add safe migration notes for new memory architecture"
Task 10: Validação final e critérios de aceite
Files:
- No new files required
Step 1: Rodar suíte de memória Run:
cd tauri-app && npm test -- src/hooks/useMemoryExtractor.test.ts src/lib/memory-parser.test.ts src/lib/user-memory-consolidator.test.ts src/lib/memory-prompt-context.test.ts
Expected: PASS
Step 2: Rodar suíte principal Run:
cd tauri-app && npm test
cd tauri-app && npm run build
Expected: PASS
Step 3: Validação manual Verificar:
- mensagem normal continua funcionando
- memórias de chat são criadas
- memórias de usuário aparecem só quando novas/mais fortes
- duplicatas não são inseridas
- se modelo de memória falhar, chat continua estável
Step 4: Commit final
git add .
git commit -m "feat: add safe chat and user memory architecture"
Riscos e mitigação
Risco 1: O modelo gemma-3-270m-it-Q8_0.gguf não ser bom para extração factual
Mitigação:
- manter parser robusto
- limitar escopo a fatos atômicos
- usar confiança + deduplicação conservadora
- tratar esse modelo como extractor heurístico, não como verdade absoluta
Risco 2: Duplicação excessiva
Mitigação:
- chave normalizada
- valor normalizado
- consolidação só com fatos novos ou confiança melhor
Risco 3: Impacto de performance
Mitigação:
- debounce
- background only
- janelas pequenas de contexto
- consolidação de usuário menos frequente que extração de chat
Risco 4: Quebra do fluxo atual
Mitigação:
- schema aditivo
- falhas silenciosas
- nenhuma injeção automática no prompt principal nesta fase
Critérios de aceitação
- O chat principal continua funcionando sem regressão.
- O sistema usa o modelo
models/embedding/gemma-3-270m-it-Q8_0.ggufexclusivamente para a pipeline de memória. - Memórias de chat são estruturadas, classificadas e persistidas separadamente.
- Memórias de usuário são geradas a partir das memórias de chat já processadas.
- O sistema não duplica memórias equivalentes.
- Existe builder separado para uso futuro dessas memórias em prompts.
- Falhas na pipeline de memória não quebram chat, build ou testes.
Recomendação de rollout
Release 1
- schema novo
- extractor de chat
- consolidator de usuário
- sem injeção no prompt principal
Release 2
- leitura controlada de
user_memories_v2+chat_memoriesem prompt dinâmico - observabilidade de qualidade
Release 3
- integração com pesquisa web + contexto híbrido
- memória + pesquisa + multiagente no orquestrador final