English: SQLite.en.md
Guía operativa del esquema SQLite actual, su creación en runtime y las consultas de diagnóstico. El horizonte migrado es 0030_items_collection_title_index.
| Capa | Autoridad | Qué crea |
|---|---|---|
| Esquema migrado | packages/store/src/runner.ts, migraciones 0001..0030 y schema_full.sql |
Tablas de negocio, vec_assets, rag_chunks, FTS e índices/triggers de migración |
| Inicio/runtime Rust | lib.rs, nlp/embeddings.rs, sync/schema.rs |
app_settings, reparaciones compatibles, rag_asset_embedding_state y nueve tablas sync_* |
| Internas de SQLite/FTS5 | SQLite | sqlite_sequence y tablas shadow de fts_items/rag_chunks_fts |
packages/store/src/schema.ts es un modelo ORM parcial. No reemplaza al DDL migrado ni al DDL creado por Rust.
Tauri resuelve app.path().app_data_dir() desde el identifier efectivo y abre entropia.sqlite dentro de ese directorio.
| Variante | Configuración | Ruta |
|---|---|---|
| Pro | tauri.conf.json: com.entropia.pro.desktop |
%APPDATA%\com.entropia.pro.desktop\entropia.sqlite |
| Lite | tauri.lite.conf.json: com.entropia.lite |
%APPDATA%\com.entropia.lite\entropia.sqlite |
| Desarrollo explícito | tauri.dev.conf.json: com.entropia.pro.desktop.dev |
%APPDATA%\com.entropia.pro.desktop.dev\entropia.sqlite |
| Legacy reconocido | constante com.entropia.app en lib.rs |
%APPDATA%\com.entropia.app\entropia.sqlite |
El backend no usa la ruta legacy como base activa. Antes de abrir la base actual, migra o combina el directorio legacy, compara la riqueza de ambas bases cuando existen las dos, conserva un backup antes de reemplazar la actual y reescribe rutas legacy de assets. El marcador .legacy-app-dir-merged evita repetir el merge completo.
Abrir una variante con sqlite3:
sqlite3 "$env:APPDATA\com.entropia.pro.desktop\entropia.sqlite"
sqlite3 "$env:APPDATA\com.entropia.lite\entropia.sqlite"
sqlite3 "$env:APPDATA\com.entropia.pro.desktop.dev\entropia.sqlite"- Rust resuelve el directorio, migra el directorio legacy y abre conexiones UI/worker con
PRAGMA journal_mode=WALyPRAGMA foreign_keys=ON. - Rust aplica reparaciones idempotentes para bases antiguas y asegura
layouts,app_settings,vec_assets,rag_asset_embedding_statey el esquema sync cuando sus subsistemas arrancan. - El frontend ejecuta
runMigrations()en orden lexicográfico desde0001_initialhasta0030_items_collection_title_indexy registra cada nombre en_migrations. 0020_layoutsse aplica programáticamente para normalizar la tabla legacy y agregarblocks;0025,0027y0029usanBEGIN IMMEDIATEpor contener rebuilds o DDL multi-statement sensible;0030es unCREATE INDEXsimple y no lo necesita.- Sync vuelve a ejecutar
ensure_capturedespués de las migraciones para crear triggers sobre todas las tablas ya disponibles.
apps/desktop/src-tauri/tests/fixtures/schema_full.sql representa el resultado migrado de una instalación nueva. No incluye las tablas exclusivamente runtime (app_settings, rag_asset_embedding_state, sync_*) ni las tablas shadow que SQLite crea al materializar FTS5.
collections, items, assets, notes, topics, item_topics, annotations, entities, triples, extractions, transcriptions, layouts, llm_results, rag_conversations, rag_messages.
_migrations, vec_assets, rag_chunks, fts_items, rag_chunks_fts.
app_settings, rag_asset_embedding_state, sync_meta, sync_oplog, sync_row_versions, sync_conflicts, sync_pending_rows, sync_pending_blobs, sync_pending_fts, sync_topic_aliases, sync_blob_index.
sqlite_sequence, por elAUTOINCREMENTde_migrations.fts_items_config,fts_items_data,fts_items_docsize,fts_items_idx.rag_chunks_fts_config,rag_chunks_fts_content,rag_chunks_fts_data,rag_chunks_fts_docsize,rag_chunks_fts_idx.
Las tablas shadow son implementación de FTS5, no entidades de negocio. Una base vieja también puede conservar vec_items o embeddings_fallback; son leftovers legacy y no pertenecen al contrato runtime actual. La migración histórica 0021_drop_unused_processing_table elimina jobs, pero 0021 no es el horizonte actual.
El árbol usa el orden canónico de una instalación nueva; una tabla layouts actualizada desde un formato legacy puede conservar blocks al final por efecto de ALTER TABLE. rowid implícito no se repite salvo donde forma parte del contrato FTS.
entropia.sqlite
├── migrado: negocio
│ ├── collections: id, name, description, created_at, updated_at
│ ├── items: id, title, collection_id, metadata, created_at, updated_at, search_text
│ ├── assets: id, item_id, path, type, size, created_at, sort_index, parent_asset_id, page_number
│ ├── notes: id, item_id, content, created_at, updated_at, asset_id
│ ├── topics: id, name, created_at
│ ├── item_topics: id, item_id, topic_id, created_at
│ ├── annotations: id, asset_id, page, kind, color, x, y, width, height, created_at, updated_at
│ ├── entities: id, item_id, entity_type, value, start_offset, end_offset, confidence, source, model_name, created_at, latitude, longitude, geo_status, asset_id, manual_lat, manual_lon
│ ├── triples: id, item_id, subject, predicate, object, created_at, asset_id
│ ├── extractions: id, asset_id, text_content, method, confidence, created_at
│ ├── transcriptions: id, asset_id, text_content, language, duration_ms, model, segments, confidence, created_at
│ ├── layouts: id, asset_id, regions, blocks, model, image_width, image_height, created_at
│ ├── llm_results: id, target_id, target_type, job_type, result, created_at
│ ├── rag_conversations: id, title, created_at, updated_at
│ └── rag_messages: id, conversation_id, sort_index, role, content, sources, model, created_at
├── migrado: técnico/RAG
│ ├── _migrations: id, name, applied_at
│ ├── vec_assets: asset_id, item_id, embedding, embedding_model, embedding_contract, dimensions
│ ├── rag_chunks: id, asset_id, item_id, source_kind, source_id, chunk_ordinal, text_content, start_char, end_char, source_text_hash, chunking_contract, embedding, embedding_model, embedding_contract, dimensions
│ ├── fts_items: item_id, title, metadata, extracted_text
│ └── rag_chunks_fts: chunk_id, text_content
├── runtime Rust
│ ├── app_settings: key, value
│ ├── rag_asset_embedding_state: asset_id, item_id, rag_incomplete, failure_count, next_retry_at_ms, last_error, updated_at_ms
│ ├── sync_meta: key, value
│ ├── sync_oplog: seq, table_name, row_id, op, changed_at
│ ├── sync_row_versions: table_name, row_id, server_seq
│ ├── sync_conflicts: id, table_name, row_id, reason, loser_payload, winner_summary, created_at, acknowledged
│ ├── sync_pending_rows: table_name, row_id, server_seq, deleted, changed_at, device_id, payload, retry_count, parked_schema_head
│ ├── sync_pending_blobs: asset_id, sha256, rel_path, size, retry_count, last_error, last_attempt_at
│ ├── sync_pending_fts: item_id
│ ├── sync_topic_aliases: remote_id, local_id
│ └── sync_blob_index: asset_id, sha256, size, file_mtime_ms, uploaded
└── shadow FTS5
├── fts_items_config: k, v
├── fts_items_data: id, block
├── fts_items_docsize: id, sz
├── fts_items_idx: segid, term, pgno
├── rag_chunks_fts_config: k, v
├── rag_chunks_fts_content: id, c0, c1
├── rag_chunks_fts_data: id, block
├── rag_chunks_fts_docsize: id, sz
└── rag_chunks_fts_idx: segid, term, pgno
El contrato formal (tipos semánticos por columna, unidades de timestamp, formas de JSON/BLOB) está materializado en el manifest de entropiaR (inst/schemas/manifest.json del paquete R) y se aplica al materializar con entropia_collect(). Esta sección resume lo que un cliente de solo lectura debe aplicar.
| Unidad | Criterio de magnitud | Columnas |
|---|---|---|
| Epoch ms (13 dígitos) | valor ≥ 1e12 | created_at/updated_at de collections, items, assets, extractions, transcriptions, layouts, notes, annotations, llm_results, rag_conversations, rag_messages; sync_conflicts.created_at; rag_asset_embedding_state.next_retry_at_ms/updated_at_ms |
| Epoch segundos (10 dígitos) | valor < 1e12 | _migrations.applied_at |
datetime_auto (ms o segundos) |
guard < 1e12 ⟹ segundos |
entities.created_at, triples.created_at |
| ISO-8601 string | dentro de JSON | items.metadata.__entropia_file_metadata.importedAt (YYYY-MM-DDTHH:MM:SSZ) |
entities.created_atytriples.created_attienen como DDL defaultstrftime('%s','now')(epoch segundos), pero la app escribe epoch ms en la práctica. Un cliente debe aplicar el guard de magnitud< 1e12(la misma regla que usó la migración0019), no asumir una sola unidad.
| Columna | Shape |
|---|---|
items.metadata |
objeto; __entropia_file_metadata anidado (original_name, original_path, importedAt ISO-8601) |
transcriptions.segments |
array de {start_ms, end_ms, text} |
layouts.regions / layouts.blocks |
arrays de regiones/bloques |
rag_messages.sources |
array de citas |
llm_results.result |
resultado del job (texto o JSON según job_type) |
sync_conflicts.loser_payload / winner_summary |
payloads del conflicto LWW |
vec_assets.embedding y rag_chunks.embedding son vectores f32 little-endian crudos: dimensions × 4 bytes (1024 dims = 4096 bytes). No deben seleccionarse por defecto en joins; el acceso es explícito (en entropiaR, with_vector = TRUE).
| Tabla | Formato |
|---|---|
extractions |
ext- ∥ asset_id |
transcriptions |
trx- ∥ asset_id |
layouts |
lay- ∥ asset_id |
llm_results |
llr-{target_type}-{target_id}-{job_type} |
rag_chunks |
ragchk- ∥ sha256 del contenido |
El resto de PK son TEXT UUIDv4; la PK de vec_assets es asset_id.
entities.source = 'manual_deleted'= soft-delete: la fila persiste pero la app la oculta. Un lector que quiera el conjunto visible debe filtrarla.app_settingsguarda claves de API (*_api_key) y no forma parte de ninguna superficie de lectura deentropiaR; un cliente no debe exponer sus valores crudos.sync_metasí tiene keys permitidas (ver sección sync).
notes/entities/triples.asset_id, llm_results.target_id, rag_chunks.source_id (→ extractions.id/transcriptions.id según source_kind) y las referencias sync (sync_row_versions.row_id, etc.) no tienen constraint física. PRAGMA foreign_keys está activo solo donde hay FK declarada; un cliente debe validar estas referencias por su cuenta.
| Tabla | PK | FK físicas y constraints principales |
|---|---|---|
_migrations |
id AUTOINCREMENT |
name UNIQUE NOT NULL |
collections |
id |
name, created_at, updated_at NOT NULL |
items |
id |
collection_id -> collections.id; search_text es GENERATED STORED |
assets |
id |
item_id -> items.id; parent_asset_id -> assets.id ON DELETE CASCADE; UNIQUE parcial (parent_asset_id, page_number) cuando el padre no es NULL |
notes |
id |
item_id -> items.id; asset_id es referencia conceptual sin FK física |
topics |
id |
name UNIQUE NOT NULL |
item_topics |
id |
ambas FK tienen ON DELETE CASCADE; UNIQUE (item_id, topic_id) |
annotations |
id |
asset_id -> assets.id ON DELETE CASCADE; kind IN ('rectangle','underline','crop','erase','rotation') |
entities |
id |
item_id -> items.id ON DELETE CASCADE; asset_id conceptual; entity_type tiene CHECK; defaults de offsets/confidence/geo_status |
triples |
id |
item_id -> items.id ON DELETE CASCADE; asset_id conceptual |
extractions |
id |
asset_id -> assets.id ON DELETE CASCADE; UNIQUE (asset_id) |
transcriptions |
id |
asset_id -> assets.id ON DELETE CASCADE; UNIQUE (asset_id) |
layouts |
id |
asset_id -> assets.id ON DELETE CASCADE; UNIQUE (asset_id), por lo tanto 0..1 layout por asset; blocks DEFAULT '[]' |
llm_results |
id |
target_id conceptual; target_type IN ('asset','item','collection','unknown') |
rag_conversations |
id |
timestamps y título NOT NULL |
rag_messages |
id |
conversation_id -> rag_conversations.id ON DELETE CASCADE; role IN ('user','assistant') |
vec_assets |
asset_id |
sin FK física; item_id, embedding y contrato NOT NULL |
rag_chunks |
id |
FK a assets e items, ambas CASCADE; source_kind IN ('extraction','transcription'); offsets/dimensiones con CHECK; UNIQUE (asset_id, source_kind, source_id, chunk_ordinal) |
rag_asset_embedding_state |
asset_id |
sin FK física; flags/contadores/timestamps con defaults 0 |
app_settings, sync_meta |
key |
value NOT NULL |
sync_oplog |
seq AUTOINCREMENT |
op IN ('I','U','D') |
sync_row_versions |
(table_name, row_id) |
sin FK físicas |
sync_pending_rows |
(table_name, row_id) |
defaults de retry; sin FK físicas |
sync_conflicts |
id |
acknowledged DEFAULT 0 |
sync_pending_blobs |
asset_id |
retry_count DEFAULT 0 |
sync_pending_fts |
item_id |
sin FK física |
sync_topic_aliases |
remote_id |
local_id NOT NULL |
sync_blob_index |
asset_id |
uploaded DEFAULT 0 |
rag_chunks.source_id apunta lógicamente a extractions.id o transcriptions.id según source_kind, pero no tiene FK física. Lo mismo ocurre con varias referencias auxiliares y sync: su integridad depende del runtime.
- Items/assets:
idx_items_search(search_text),idx_items_collection(collection_id),idx_assets_item(item_id),idx_assets_item_sort(item_id, sort_index),idx_assets_parent_asset_id(parent_asset_id),idx_assets_parent_page(parent_asset_id, page_number)UNIQUE parcial,idx_items_collection_title(collection_id, title COLLATE NOCASE, id). idx_items_collection_titlecubre de punta a punta la consulta de la grilla de colecciones: el filtro porcollection_id, elORDER BY title COLLATE NOCASE, idy el cursor keyset construido sobre ese mismo par. Sin las columnas de orden en el índice, SQLite filtra poridx_items_collectiony después ordena todo el resultado en un b-tree temporal cada vez que se abre una colección.- Derivados por asset:
idx_extractions_asset_id,idx_extractions_asset_id_uniqueUNIQUE,idx_transcriptions_asset_id,idx_transcriptions_asset_id_uniqueUNIQUE,idx_layouts_asset_id,idx_layouts_asset_id_uniqueUNIQUE,annotations_asset_id_idx,annotations_asset_page_idx. - Semántica:
idx_notes_item,idx_notes_asset_id,idx_entities_item_id,idx_entities_type,idx_entities_geo_status,idx_entities_asset_id,triples_item_id_idx,idx_triples_asset_id. - Topics/LLM:
idx_item_topics_item_topicUNIQUE,idx_item_topics_topic_id,idx_llm_results_target,idx_llm_results_target_typed.
idx_rag_messages_conversation(conversation_id, sort_index).idx_vec_assets_item_id(item_id).idx_rag_chunks_asset_id(asset_id),idx_rag_chunks_item_id(item_id),idx_rag_chunks_embedding_contract(embedding_model, embedding_contract, dimensions).idx_rag_asset_embedding_state_due(rag_incomplete, next_retry_at_ms).idx_sync_oplog_row(table_name, row_id).
SQLite también crea índices automáticos para PK/UNIQUE; no se enumeran porque sus nombres sqlite_autoindex_* son detalles de implementación.
| Familia | Cantidad | Alcance | Comportamiento |
|---|---|---|---|
collection_activity_* |
33 | 11 tablas x INSERT/UPDATE/DELETE | Actualiza monotónicamente collections.updated_at para items, assets, notes, extractions, layouts, transcriptions, annotations, entities, triples, vec_assets, llm_results |
rag_chunks_fts_* |
2 | INSERT y DELETE sobre rag_chunks |
Inserta/elimina el documento correspondiente en rag_chunks_fts |
trg_sync_* |
48 | 16 tablas x INSERT/UPDATE/DELETE | Agrega operaciones a sync_oplog cuando capture está habilitado y no se está aplicando un pull |
La allowlist sync exacta es: collections, items, assets, notes, annotations, extractions, transcriptions, layouts, entities, triples, topics, item_topics, llm_results, rag_conversations, rag_messages, vec_assets.
rag_chunks y rag_asset_embedding_state no están en la allowlist sync: chunks y estado de reparación son derivados/locales. Tampoco se sincronizan tablas FTS ni sync_*. Los triggers sync requieren sync_meta.capture_enabled='1' y sync_meta.applying<>'1'; sin device_id, ensure_capture vacía sync_oplog. La versión actual del template es triggers_version='2'.
rag_chunks_fts no tiene trigger UPDATE. El runtime reemplaza chunks mediante delete/insert; una actualización SQL manual de rag_chunks.text_content dejaría el FTS desfasado y debe evitarse o acompañarse de una reindexación explícita.
fts_items usa content='' y tokenizer unicode61 remove_diacritics 1. Sus columnas declaradas no son contenido recuperable: en una tabla contentless pueden leerse como NULL. El contrato es fts_items.rowid = items.rowid; toda lectura de identidad/título/metadata debe hacer JOIN con items por rowid.
SELECT
i.id AS item_id,
i.title,
bm25(fts_items) AS rank
FROM fts_items
JOIN items i ON i.rowid = fts_items.rowid
WHERE fts_items MATCH 'archivo OR documento'
ORDER BY bm25(fts_items)
LIMIT 20;No uses SELECT item_id, title FROM fts_items para recuperar payload ni borres por item_id. Los inserts escriben rowid explícito; ante drift, el procedimiento seguro es INSERT INTO fts_items(fts_items) VALUES('delete-all') seguido de rebuild. 0004 establece el baseline y 0018 corrige bases existentes.
rag_chunks_fts conserva chunk_id y text_content; se vincula a rag_chunks.id y usa el mismo tokenizer.
SELECT
rc.id AS chunk_id,
rc.asset_id,
rc.item_id,
rc.source_kind,
rc.chunk_ordinal,
snippet(rag_chunks_fts, 1, '[', ']', '...', 20) AS preview
FROM rag_chunks_fts
JOIN rag_chunks rc ON rc.id = rag_chunks_fts.chunk_id
WHERE rag_chunks_fts MATCH 'archivo OR documento'
ORDER BY bm25(rag_chunks_fts)
LIMIT 20;collections 1 ── N items 1 ── N assets
├── 0..1 extractions
├── 0..1 transcriptions
├── 0..1 layouts
├── 0..1 vec_assets
├── 0..N annotations
├── 0..N rag_chunks
├── 0..1 rag_asset_embedding_state (conceptual/runtime)
└── 0..N child assets (parent_asset_id)
items ──< notes / entities / triples / rag_chunks
items >──< topics via item_topics
rag_conversations 1 ── N rag_messages
fts_items.rowid ── items.rowid
rag_chunks_fts.chunk_id ── rag_chunks.id
erDiagram
collections ||--o{ items : contains
items ||--o{ assets : has
assets o|--o{ assets : parent_of
items ||--o{ notes : has
items ||--o{ entities : extracts
items ||--o{ triples : derives
items ||--o{ item_topics : tagged_with
topics ||--o{ item_topics : groups
assets ||--o| extractions : produces
assets ||--o| transcriptions : produces
assets ||--o| layouts : has
assets ||--o| vec_assets : embeds
assets ||--o{ annotations : has
assets ||--o{ rag_chunks : chunks
items ||--o{ rag_chunks : owns
rag_conversations ||--o{ rag_messages : contains
assets ||--o| rag_asset_embedding_state : repair_state
Las relaciones con rag_asset_embedding_state, FTS y varias columnas asset_id auxiliares son conceptuales; la tabla de constraints anterior distingue el enforcement físico.
Estas consultas inspeccionan la base que realmente abriste; no presuponen que todas las capas runtime ya se hayan inicializado.
.tables
.schema
SELECT type, name, tbl_name
FROM sqlite_master
WHERE name NOT LIKE 'sqlite_autoindex_%'
ORDER BY type, name;
SELECT name, applied_at
FROM _migrations
ORDER BY name DESC
LIMIT 10;
SELECT name
FROM _migrations
WHERE name = '0030_items_collection_title_index';
PRAGMA table_xinfo(items);
PRAGMA foreign_key_list(assets);
PRAGMA index_list(rag_chunks);El inventario de esta guía se deriva del fixture migrado y de los DDL runtime autoritativos; no afirma haber consultado una base de usuario concreta. En una base real pueden faltar tablas runtime todavía no inicializadas o aparecer leftovers legacy.
SELECT
a.id,
a.item_id,
a.parent_asset_id,
a.page_number,
a.path,
a.type,
a.sort_index,
CASE WHEN e.asset_id IS NOT NULL THEN 1 ELSE 0 END AS has_extraction,
CASE WHEN t.asset_id IS NOT NULL THEN 1 ELSE 0 END AS has_transcription,
CASE WHEN l.asset_id IS NOT NULL THEN 1 ELSE 0 END AS has_layout
FROM assets a
LEFT JOIN extractions e ON e.asset_id = a.id
LEFT JOIN transcriptions t ON t.asset_id = a.id
LEFT JOIN layouts l ON l.asset_id = a.id
WHERE a.item_id = 'ITEM_ID'
ORDER BY a.sort_index, a.page_number, a.created_at;SELECT id, title, collection_id, metadata, search_text, created_at, updated_at
FROM items
WHERE id = 'ITEM_ID';
SELECT id, asset_id, model, image_width, image_height, regions, blocks, created_at
FROM layouts
WHERE asset_id = 'ASSET_ID';
SELECT
id,
item_id,
asset_id,
entity_type,
value,
confidence,
latitude,
longitude,
manual_lat,
manual_lon,
geo_status,
source,
model_name
FROM entities
WHERE item_id = 'ITEM_ID'
ORDER BY confidence DESC, value;
SELECT id, asset_id, page, kind, color, x, y, width, height, created_at, updated_at
FROM annotations
WHERE asset_id = 'ASSET_ID'
ORDER BY page, created_at;SELECT
c.id AS conversation_id,
c.title,
m.id AS message_id,
m.sort_index,
m.role,
m.model,
m.created_at,
m.content,
m.sources
FROM rag_conversations c
LEFT JOIN rag_messages m ON m.conversation_id = c.id
WHERE c.id = 'CONVERSATION_ID'
ORDER BY m.sort_index;SELECT
id,
asset_id,
item_id,
source_kind,
source_id,
chunk_ordinal,
start_char,
end_char,
length(text_content) AS text_chars,
length(embedding) AS embedding_bytes,
embedding_model,
embedding_contract,
dimensions,
chunking_contract
FROM rag_chunks
WHERE asset_id = 'ASSET_ID'
ORDER BY source_kind, source_id, chunk_ordinal;SELECT
asset_id,
item_id,
length(embedding) AS embedding_bytes,
embedding_model,
embedding_contract,
dimensions
FROM vec_assets
WHERE asset_id = 'ASSET_ID';SELECT
asset_id,
item_id,
rag_incomplete,
failure_count,
next_retry_at_ms,
datetime(next_retry_at_ms / 1000, 'unixepoch', 'localtime') AS next_retry_local,
last_error,
updated_at_ms
FROM rag_asset_embedding_state
WHERE rag_incomplete = 1
ORDER BY next_retry_at_ms, asset_id;Una fila marca persistencia RAG incompleta o un retry pendiente. Al completarse correctamente vec_assets + rag_chunks, el runtime elimina la fila de estado; ausencia de fila no significa por sí sola que exista un embedding.
SELECT key, value
FROM sync_meta
ORDER BY key;
SELECT table_name, row_id, MAX(seq) AS latest_seq, COUNT(*) AS operations
FROM sync_oplog
GROUP BY table_name, row_id
ORDER BY latest_seq;
SELECT id, table_name, row_id, reason, created_at, acknowledged
FROM sync_conflicts
WHERE acknowledged = 0
ORDER BY created_at DESC;
SELECT 'pending_rows' AS queue, COUNT(*) AS pending FROM sync_pending_rows
UNION ALL
SELECT 'pending_blobs', COUNT(*) FROM sync_pending_blobs
UNION ALL
SELECT 'pending_fts', COUNT(*) FROM sync_pending_fts;
SELECT table_name, COUNT(*) AS versioned_rows, MAX(server_seq) AS latest_server_seq
FROM sync_row_versions
GROUP BY table_name
ORDER BY table_name;
SELECT uploaded, COUNT(*) AS blobs, SUM(size) AS bytes
FROM sync_blob_index
GROUP BY uploaded
ORDER BY uploaded;
SELECT remote_id, local_id
FROM sync_topic_aliases
ORDER BY remote_id;
SELECT COUNT(*) AS sync_trigger_count
FROM sqlite_master
WHERE type = 'trigger' AND name LIKE 'trg_sync_%';
SELECT name, tbl_name
FROM sqlite_master
WHERE type = 'trigger' AND name LIKE 'trg_sync_%'
ORDER BY tbl_name, name;En un esquema completamente migrado y con capture asegurado, el conteo esperado es 48. Un valor menor puede indicar que faltan tablas/migraciones o que ensure_capture todavía no se reejecutó.
- Confirmá que abriste la ruta de la variante correcta.
- Verificá que
_migrationscontenga0030_items_collection_title_index, el horizonte actual. - Revisá
PRAGMA foreign_keys,journal_modey la estructura real contable_xinfo/index_list. - Para FTS de ítems, uní
fts_itemsconitemsporrowid; no leas payload de la tabla contentless. - Para RAG, revisá en conjunto
vec_assets,rag_chunks,rag_chunks_ftsyrag_asset_embedding_state. - Para sync, revisá sesión/capture en
sync_meta, oplog, pendientes, conflictos y los 48 triggers. - Tratá
schema.ts, tablas shadow y leftovers legacy según su capa; no los confundas con el esquema físico migrado completo.