18 KiB
Tauri Physical SQLite Migration Implementation Plan
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Migrar o armazenamento atual baseado em sql.js + localStorage para um SQLite físico real no Tauri, com melhor performance, durabilidade e estrutura de recuperação de contexto adequada para workloads de IA e memória.
Architecture: A migração será feita de forma incremental, introduzindo primeiro uma camada de acesso a dados em Rust/Tauri com SQLite físico como source of truth, enquanto mantemos um caminho de compatibilidade temporária para importação do banco legado do localStorage. O frontend não consultará banco diretamente em nenhuma hipótese: toda leitura e escrita passará pelo backend via comandos/APIs Tauri orientados a domínio (chat, message, memory, migration, search, summary), reduzindo acoplamento, melhorando performance e preparando a base para estratégias de compressão/recall que economizam tokens.
Tech Stack: Tauri + Rust, SQLite físico local, comandos Tauri (invoke), React/TypeScript frontend, migração do legado sql.js, Vitest + testes Rust.
Recomendação explícita: caminho ideal
Escolha recomendada
Implementar SQLite físico via backend Rust/Tauri como source of truth, com DAO/repositórios tipados e API de domínio para o frontend.
Motivo
Esse é o melhor caminho para o seu produto porque oferece:
- mais performance real que
sql.js + localStorage - durabilidade de verdade (arquivo físico)
- concorrência/controlabilidade melhores
- ferramentas reais de inspeção e manutenção (
sqlite3, DB Browser for SQLite, LiteCLI, Datasette, SQLx/rusqlite) - base ideal para memória, recall, sumarização e deduplicação, que são as partes que mais ajudam a reduzir tokens em apps de IA
Escolha técnica recomendada de biblioteca Rust
Recomendação principal: rusqlite
Motivo:
- simples
- rápido
- excelente para SQLite local embedded
- controle fino sobre pragmas, índices, transações, FTS5
- ideal para Tauri desktop local-first
Escolha de schema para IA/memória
Recomendação principal: SQLite relacional + FTS5 + tabelas de memória estruturadas
Motivo:
- reduz tokens ao permitir:
- recall seletivo por chat
- busca lexical rápida com FTS5
- consolidação e deduplicação de memória
- recuperação por categoria/confiança/recência
- evita mandar histórico bruto inteiro ao modelo
O que muda conceitualmente
Hoje
- banco em memória (
sql.js) - persistência em
localStorage - frontend executa SQL diretamente
- schema simples, pouca rastreabilidade para memória
Depois
- banco físico em arquivo SQLite real
- backend Rust controla schema, migração e consultas
- frontend usa API de domínio, não SQL cru
- schema otimizado para:
- chats n - mensagens
- memória de chat
- memória de usuário
- FTS para recuperação
- jobs de processamento
- metadados de compressão/contexto
Benefícios esperados para IA e economia de tokens
1. Recuperação seletiva
Em vez de reenviar 20+ mensagens sempre, o app poderá consultar:
- últimas mensagens do chat
- memórias de chat com alta confiança
- memórias de usuário relevantes
- snippets recuperados por FTS5
2. Context packing mais barato
Você poderá montar prompts com:
- fatos duráveis
- resumo do chat
- poucos trechos relevantes
- não o histórico bruto completo
3. Estrutura para compressão e summaries
SQLite físico facilita adicionar depois:
- tabela de
chat_summaries - snapshots de contexto
- fragments de recall
- ranking por recência/relevância/confiança
4. Ferramentas melhores
Você ganha ferramentas de inspeção e tuning reais:
sqlite3- DB Browser for SQLite
EXPLAIN QUERY PLAN- FTS5
- índices compostos
- WAL mode
Arquitetura alvo recomendada
Camada 1 — Storage engine
Arquivo físico SQLite, por exemplo em:
- diretório de app data do Tauri
- ex.:
ForgeLM/forgelm.sqlite3
Pragmas recomendados
journal_mode = WALsynchronous = NORMALforeign_keys = ONtemp_store = MEMORYcache_sizeajustado
Esses pragmas equilibram performance e segurança para desktop local.
Camada 2 — Backend service layer (source of truth)
Criar módulos Rust como:
chat_service.rsmessage_service.rsmemory_service.rsmigration_service.rssearch_service.rssummary_service.rs
Esses serviços usam repositórios SQLite internamente, mas expõem contratos estáveis para a camada de API.
Camada 3 — Backend API / Tauri commands
O backend deve servir tudo que o frontend precisar. O frontend não acessa banco, SQL, arquivo SQLite, sql.js ou localStorage como fonte operacional.
Exemplos de endpoints/commands:
chat_listchat_getchat_createchat_renamechat_deletemessage_list_by_chatmessage_create_usermessage_create_assistantmessage_updatemessage_deletememory_chat_listmemory_user_listmemory_reprocess_chatmemory_consolidate_usercontext_searchsummary_get_by_chatlegacy_importdb_health
Camada 4 — Frontend API client
No frontend, criar uma camada única de acesso:
tauri-app/src/lib/backend-client.ts
Ela substitui qualquer acesso direto a banco e fala apenas com o backend via invoke().
Schema recomendado
Tabela chats
Manter, com pequenos aprimoramentos. Campos:
idtitlecreated_atupdated_atarchived_at NULLsummary_updated_at NULL
Tabela messages
Campos:
idchat_idrolecontentreasoning_contentdisplay_modeforgeagent_stateprompt_tokenscompletion_tokenstotal_tokenstokens_per_secondmemory_processedcontent_hashcreated_at
Tabela chat_memories
Para memórias derivadas de um chat.
Tabela user_memories
Versão nova consolidada.
Tabela memory_jobs
Controle de processamento.
Tabela chat_summaries
Recomendação importante: já criar a tabela, mesmo que não seja usada imediatamente. Campos sugeridos:
idchat_idsummary_type(rolling,milestone,session)summary_textsource_message_start_idsource_message_end_idcreated_at
Tabela virtual FTS5
Recomendação forte:
message_searchvia FTS5 sobremessages.content- possivelmente FTS também sobre memórias/summaries depois
Isso será um dos maiores ganhos para reduzir tokens no futuro.
Estratégia de migração segura
Fase 0 — Compatibilidade
Não remover o sql.js imediatamente.
Fase 1 — Criar banco físico e schema novo
- app continua funcionando
- banco físico nasce vazio
Fase 2 — Implementar importador do legado
- ler
forgelm_db_v2dolocalStorage - converter para o schema novo
- importar uma única vez com flag de migração
Fase 3 — Trocar frontend para db-client
- componentes deixam de falar SQL direto
- passam a chamar Tauri commands
Fase 4 — Desligar sql.js
- só depois de validar import, escrita, leitura, edição e build
Plano por fases
Task 1: Congelar comportamento atual com testes de regressão
Files:
- Modify:
tauri-app/src/lib/db.test.ts - Modify:
tauri-app/src/App.test.tsx - Modify:
tauri-app/src/components/ChatView.test.tsx
Step 1: Escrever testes de comportamento atual Cobrir:
- criar chat
- carregar histórico
- inserir mensagem user/assistant
- editar/deletar
- persistir métricas
Step 2: Rodar testes Run:
cd tauri-app && npm test -- src/lib/db.test.ts src/App.test.tsx src/components/ChatView.test.tsx
Expected: PASS
Step 3: Commit
git add tauri-app/src/lib/db.test.ts tauri-app/src/App.test.tsx tauri-app/src/components/ChatView.test.tsx
git commit -m "test: freeze current chat db behavior before sqlite migration"
Task 2: Introduzir backend SQLite físico no Rust/Tauri
Files:
- Create:
src-tauri/src/db/mod.rs - Create:
src-tauri/src/db/schema.rs - Create:
src-tauri/src/db/connection.rs - Modify:
src-tauri/src/main.rs - Test: Rust unit tests in
src-tauri/src/db/*
Step 1: Escrever testes falhos de inicialização Cobrir:
- cria arquivo físico
- aplica schema
- ativa pragmas corretos
Step 2: Implementar conexão SQLite com rusqlite
- path em diretório de app data do Tauri
- abrir conexão singleton ou pool simples controlado
Step 3: Aplicar schema inicial
Criar tabelas chats, messages, user_memories, chat_memories, memory_jobs, chat_summaries, FTS5.
Step 4: Rodar testes Rust Run:
cargo test db -- --nocapture
Expected: PASS
Step 5: Commit
git add src-tauri/src/db src-tauri/src/main.rs
git commit -m "feat: add physical sqlite backend for tauri"
Task 3: Implementar repositórios Rust e service layer orientados a domínio
Files:
- Create:
src-tauri/src/db/chat_repository.rs - Create:
src-tauri/src/db/message_repository.rs - Create:
src-tauri/src/db/memory_repository.rs - Create:
src-tauri/src/services/chat_service.rs - Create:
src-tauri/src/services/message_service.rs - Create:
src-tauri/src/services/memory_service.rs - Test: Rust tests per repository/service
Step 1: Escrever testes falhos por repositório e service Cobrir:
- CRUD de chats
- insert/list de mensagens
- leitura por chat
- atualização de timestamps
- contratos de service retornando DTOs estáveis
Step 2: Implementar repositórios mínimos Acesso bruto ao SQLite.
Step 3: Implementar services Toda regra de negócio deve ficar aqui. Commands não devem montar SQL.
Step 4: Rodar testes Run:
cargo test repository -- --nocapture
cargo test service -- --nocapture
Expected: PASS
Step 5: Commit
git add src-tauri/src/db/chat_repository.rs src-tauri/src/db/message_repository.rs src-tauri/src/db/memory_repository.rs src-tauri/src/services/chat_service.rs src-tauri/src/services/message_service.rs src-tauri/src/services/memory_service.rs
git commit -m "feat: add sqlite repositories and backend service layer"
Task 4: Expor API/backend commands completos para o frontend
Files:
- Modify:
src-tauri/src/main.rs - Create:
src-tauri/src/commands/chat_commands.rs - Create:
src-tauri/src/commands/message_commands.rs - Create:
src-tauri/src/commands/memory_commands.rs - Create:
src-tauri/src/commands/system_commands.rs - Create:
tauri-app/src/lib/backend-client.ts - Test:
tauri-app/src/lib/backend-client.test.ts
Step 1: Escrever testes falhos do client Cobrir contratos como:
listChats()getChat(chatId)getMessages(chatId)createChat()createUserMessage()createAssistantMessage()listChatMemories()listUserMemories()healthCheck()
Step 2: Implementar commands Tauri Usar services Rust por trás. O frontend não deve conhecer SQL, schema ou detalhes de armazenamento.
Step 3: Implementar client TS
Centralizar chamadas invoke() em backend-client.ts.
Step 4: Rodar testes Run:
cd tauri-app && npm test -- src/lib/backend-client.test.ts
Expected: PASS
Step 5: Commit
git add src-tauri/src/commands/chat_commands.rs src-tauri/src/commands/message_commands.rs src-tauri/src/commands/memory_commands.rs src-tauri/src/commands/system_commands.rs src-tauri/src/main.rs tauri-app/src/lib/backend-client.ts tauri-app/src/lib/backend-client.test.ts
git commit -m "feat: expose backend api for chats messages memory and system"
Task 5: Adaptar frontend para falar apenas com o backend
Files:
- Modify:
tauri-app/src/lib/db.ts - Modify:
tauri-app/src/App.tsx - Modify:
tauri-app/src/components/ChatView.tsx - Modify: arquivos que usam
DBdiretamente
Step 1: Escrever testes falhos de integração
Cobrir o fluxo principal usando backend-client.
Step 2: Implementar camada de compatibilidade
Recomendação: não apagar db.ts de imediato.
Transformá-lo em façade legada ou adaptador temporário até toda a UI migrar.
Step 3: Migrar ChatView, App e demais módulos
Substituir qualquer leitura/escrita local por chamadas ao backend.
Step 4: Rodar testes frontend Run:
cd tauri-app && npm test
Expected: PASS
Step 5: Commit
git add tauri-app/src/lib/db.ts tauri-app/src/App.tsx tauri-app/src/components/ChatView.tsx
git commit -m "refactor: make frontend consume backend api only"
Task 6: Implementar importador do banco legado do localStorage
Files:
- Create:
src-tauri/src/db/import_legacy.rs - Create:
src-tauri/src/commands/migration_commands.rs - Create:
tauri-app/src/lib/legacy-db-export.ts - Test: Rust + TS tests
Step 1: Escrever testes falhos para importação Cobrir:
- chats importados
- messages importadas
- user_memories importadas
- import idempotente
Step 2: Implementar exportador legado no frontend
Transformar forgelm_db_v2 em JSON transferível.
Step 3: Implementar importador no Rust Receber JSON e inserir no SQLite físico dentro de transação.
Step 4: Criar flag de migração concluída
Pode ser tabela app_meta ou arquivo de config.
Step 5: Rodar testes Run:
cargo test import_legacy -- --nocapture
cd tauri-app && npm test -- src/lib/legacy-db-export.ts
Expected: PASS
Step 6: Commit
git add src-tauri/src/db/import_legacy.rs src-tauri/src/commands/migration_commands.rs tauri-app/src/lib/legacy-db-export.ts
git commit -m "feat: import legacy localStorage database into physical sqlite"
Task 7: Otimizar SQLite para workloads de IA e economia de tokens
Files:
- Modify:
src-tauri/src/db/connection.rs - Modify:
src-tauri/src/db/schema.rs - Create:
docs/sqlite-context-strategy.md - Test: Rust tests/query-plan checks if viable
Step 1: Ativar FTS5 Criar tabela virtual para busca textual eficiente em mensagens.
Step 2: Criar índices úteis Sugestões:
messages(chat_id, created_at)messages(role, created_at)chat_memories(chat_id, memory_category, confidence)user_memories(memory_category, confidence, updated_at)
Step 3: Preparar schema para summaries e recall
Criar chat_summaries e metadados de contexto.
Step 4: Documentar estratégia anti-token-bloat Ex.: usar FTS5 + summary + memory retrieval.
Step 5: Commit
git add src-tauri/src/db/connection.rs src-tauri/src/db/schema.rs docs/sqlite-context-strategy.md
git commit -m "feat: optimize sqlite schema for ai context retrieval"
Task 8: Desligar persistência em localStorage e manter fallback controlado
Files:
- Modify:
tauri-app/src/lib/db.ts - Modify:
tauri-app/src/App.tsx - Modify:
tauri-app/src/lib/legacy-db-export.ts
Step 1: Escrever testes falhos de pós-migração Cobrir:
- app lê do SQLite físico
- localStorage não é mais source of truth
Step 2: Remover persist() como mecanismo principal
Pode manter apenas como utilitário legado temporário, não mais ativo.
Step 3: Rodar testes Run:
cd tauri-app && npm test
cd tauri-app && npm run build
Expected: PASS
Step 4: Commit
git add tauri-app/src/lib/db.ts tauri-app/src/App.tsx tauri-app/src/lib/legacy-db-export.ts
git commit -m "refactor: disable localStorage db persistence after sqlite migration"
Task 9: Validação final ponta a ponta
Files:
- No new files required initially
Step 1: Rodar testes Rust
cargo test -- --nocapture
Step 2: Rodar testes frontend
cd tauri-app && npm test
cd tauri-app && npm run build
Step 3: Verificação manual Validar:
- criar chat
- enviar mensagens
- reiniciar app e confirmar persistência real
- importar banco legado
- editar/deletar mensagens
- inspecionar arquivo SQLite físico com ferramenta externa
Step 4: Commit final
git add .
git commit -m "feat: migrate app storage to physical sqlite in tauri"
Ferramentas recomendadas após a migração
Para desenvolvimento e debugging:
- DB Browser for SQLite — melhor opção visual simples
- sqlite3 CLI — excelente para scripts e inspeção rápida
- LiteCLI — autocomplete SQL
- Datasette (opcional) — excelente para explorar dados localmente
Para economia de tokens no futuro:
- FTS5 para recall lexical barato
- chat_summaries para compaction
- chat_memories / user_memories para fatos duráveis
- ranking por confiança + recência para montar prompt enxuto
Riscos e mitigação
Risco 1: quebrar o frontend ao remover db.ts
Mitigação: manter adaptador temporário e migrar por etapas.
Risco 2: migração incompleta do legado
Mitigação: importador idempotente + flag de migração + logs claros.
Risco 3: latência do invoke() no Tauri
Mitigação: commands orientados a domínio, não excessivamente granulares.
Risco 4: schema ainda inadequado para IA no futuro
Mitigação: já criar FTS5 + summaries + memória estruturada nesta migração.
Critérios de aceitação
- O app usa SQLite físico real como source of truth.
- O banco persiste entre reinícios do app sem depender de localStorage.
- Chats, mensagens e memórias são mantidos corretamente.
- Existe caminho de importação do banco legado.
- O frontend não depende mais de SQL direto via
sql.jspara operação normal. - O schema já suporta estratégias futuras de redução de tokens.
- Build e testes seguem verdes.
Resumo executivo
O que eu recomendo implementar
- SQLite físico real em Rust/Tauri com
rusqlite - API de domínio para o frontend
- FTS5 + schema preparado para memória e summaries
- migração incremental do legado
localStorage
Por que isso é o melhor para IA
Porque essa base permite fazer direito, depois:
- memória estruturada
- busca local eficiente
- resumos incrementais
- recall seletivo
- menos contexto bruto enviado ao modelo
- menor consumo de tokens
Aprovação para execução
Se você aprovar, eu recomendo começar por esta ordem:
- Task 1 — congelar comportamento atual
- Task 2 — subir o SQLite físico no Tauri
- Task 4 — expor commands ao frontend
- Task 6 — importação do legado
Essa é a sequência com menor risco.