| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| PRAGMA foreign_keys = ON; |
| PRAGMA journal_mode = WAL; |
|
|
| |
| |
| |
| CREATE TABLE IF NOT EXISTS entities ( |
| id TEXT PRIMARY KEY, |
| tenant_id TEXT NOT NULL, |
| category TEXT NOT NULL, |
| name TEXT NOT NULL, |
| status TEXT, |
| body TEXT NOT NULL CHECK (json_valid(body)), |
| created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')), |
| updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')), |
| UNIQUE (tenant_id, category, name) |
| ); |
|
|
| CREATE INDEX IF NOT EXISTS entities_tenant_cat_status |
| ON entities (tenant_id, category, status); |
| CREATE INDEX IF NOT EXISTS entities_updated_at |
| ON entities (tenant_id, updated_at DESC); |
|
|
| |
| |
| |
| CREATE TABLE IF NOT EXISTS entity_relations ( |
| id TEXT PRIMARY KEY, |
| tenant_id TEXT NOT NULL, |
| from_id TEXT NOT NULL REFERENCES entities(id) ON DELETE CASCADE, |
| to_id TEXT NOT NULL REFERENCES entities(id) ON DELETE CASCADE, |
| relation_type TEXT NOT NULL, |
| metadata TEXT CHECK (metadata IS NULL OR json_valid(metadata)), |
| created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')) |
| ); |
|
|
| CREATE INDEX IF NOT EXISTS entity_relations_from |
| ON entity_relations (tenant_id, from_id, relation_type); |
| CREATE INDEX IF NOT EXISTS entity_relations_to |
| ON entity_relations (tenant_id, to_id, relation_type); |
|
|
| |
| |
| |
| CREATE TABLE IF NOT EXISTS state_documents ( |
| tenant_id TEXT NOT NULL, |
| document_key TEXT NOT NULL, |
| body TEXT NOT NULL CHECK (json_valid(body)), |
| updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')), |
| PRIMARY KEY (tenant_id, document_key) |
| ); |
|
|
| |
| |
| |
| CREATE TABLE IF NOT EXISTS journal_events ( |
| id TEXT PRIMARY KEY, |
| tenant_id TEXT NOT NULL, |
| ts TEXT NOT NULL, |
| evaluated TEXT CHECK (evaluated IS NULL OR json_valid(evaluated)), |
| acted TEXT CHECK (acted IS NULL OR json_valid(acted)), |
| forward TEXT CHECK (forward IS NULL OR json_valid(forward)), |
| extra TEXT CHECK (extra IS NULL OR json_valid(extra)) |
| ); |
|
|
| CREATE INDEX IF NOT EXISTS journal_events_tenant_ts |
| ON journal_events (tenant_id, ts DESC); |
|
|
| |
| |
| |
| CREATE TABLE IF NOT EXISTS revenue_events ( |
| id TEXT PRIMARY KEY, |
| tenant_id TEXT NOT NULL, |
| ts TEXT NOT NULL, |
| event_type TEXT, |
| gross_usd REAL, |
| operator_share_usd REAL, |
| source TEXT, |
| tx TEXT, |
| entity_id TEXT REFERENCES entities(id) ON DELETE SET NULL |
| ); |
|
|
| CREATE INDEX IF NOT EXISTS revenue_events_tenant_ts |
| ON revenue_events (tenant_id, ts DESC); |
|
|
| |
| |
| |
| CREATE TABLE IF NOT EXISTS error_events ( |
| id TEXT PRIMARY KEY, |
| tenant_id TEXT NOT NULL, |
| ts TEXT NOT NULL, |
| code TEXT, |
| message TEXT, |
| context TEXT CHECK (context IS NULL OR json_valid(context)) |
| ); |
|
|
| CREATE INDEX IF NOT EXISTS error_events_tenant_ts |
| ON error_events (tenant_id, ts DESC); |
|
|
| |
| |
| |
| CREATE TABLE IF NOT EXISTS reference_documents ( |
| tenant_id TEXT NOT NULL, |
| doc_key TEXT NOT NULL, |
| body TEXT, |
| metadata TEXT CHECK (metadata IS NULL OR json_valid(metadata)), |
| updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')), |
| PRIMARY KEY (tenant_id, doc_key) |
| ); |
|
|
| |
| |
| |
| CREATE TABLE IF NOT EXISTS archived_entities ( |
| id TEXT PRIMARY KEY, |
| tenant_id TEXT NOT NULL, |
| original_entity_id TEXT, |
| category TEXT, |
| name TEXT, |
| body TEXT CHECK (body IS NULL OR json_valid(body)), |
| archived_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')), |
| archive_reason TEXT |
| ); |
|
|
| CREATE INDEX IF NOT EXISTS archived_entities_tenant_cat |
| ON archived_entities (tenant_id, category, name); |
|
|
| |
| |
| |
| CREATE TABLE IF NOT EXISTS flagged_actors ( |
| id TEXT PRIMARY KEY, |
| tenant_id TEXT NOT NULL, |
| actor_handle TEXT, |
| actor_address TEXT, |
| flagged_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')), |
| reason TEXT, |
| evidence TEXT CHECK (evidence IS NULL OR json_valid(evidence)) |
| ); |
|
|
| CREATE INDEX IF NOT EXISTS flagged_actors_tenant |
| ON flagged_actors (tenant_id); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| CREATE VIRTUAL TABLE IF NOT EXISTS entities_fts USING fts5( |
| name, category, body, tenant_id UNINDEXED, |
| content='entities', content_rowid='rowid', |
| tokenize = 'porter unicode61' |
| ); |
|
|
| CREATE TRIGGER IF NOT EXISTS entities_ai_fts |
| AFTER INSERT ON entities BEGIN |
| INSERT INTO entities_fts(rowid, name, category, body, tenant_id) |
| VALUES (new.rowid, new.name, new.category, new.body, new.tenant_id); |
| END; |
|
|
| CREATE TRIGGER IF NOT EXISTS entities_ad_fts |
| AFTER DELETE ON entities BEGIN |
| INSERT INTO entities_fts(entities_fts, rowid, name, category, body, tenant_id) |
| VALUES ('delete', old.rowid, old.name, old.category, old.body, old.tenant_id); |
| END; |
|
|
| CREATE TRIGGER IF NOT EXISTS entities_au_fts |
| AFTER UPDATE ON entities BEGIN |
| INSERT INTO entities_fts(entities_fts, rowid, name, category, body, tenant_id) |
| VALUES ('delete', old.rowid, old.name, old.category, old.body, old.tenant_id); |
| INSERT INTO entities_fts(rowid, name, category, body, tenant_id) |
| VALUES (new.rowid, new.name, new.category, new.body, new.tenant_id); |
| END; |
|
|
| |
| CREATE VIRTUAL TABLE IF NOT EXISTS state_documents_fts USING fts5( |
| document_key, body, tenant_id UNINDEXED, |
| content='state_documents', content_rowid='rowid', |
| tokenize = 'porter unicode61' |
| ); |
|
|
| CREATE TRIGGER IF NOT EXISTS state_documents_ai_fts |
| AFTER INSERT ON state_documents BEGIN |
| INSERT INTO state_documents_fts(rowid, document_key, body, tenant_id) |
| VALUES (new.rowid, new.document_key, new.body, new.tenant_id); |
| END; |
|
|
| CREATE TRIGGER IF NOT EXISTS state_documents_ad_fts |
| AFTER DELETE ON state_documents BEGIN |
| INSERT INTO state_documents_fts(state_documents_fts, rowid, document_key, body, tenant_id) |
| VALUES ('delete', old.rowid, old.document_key, old.body, old.tenant_id); |
| END; |
|
|
| CREATE TRIGGER IF NOT EXISTS state_documents_au_fts |
| AFTER UPDATE ON state_documents BEGIN |
| INSERT INTO state_documents_fts(state_documents_fts, rowid, document_key, body, tenant_id) |
| VALUES ('delete', old.rowid, old.document_key, old.body, old.tenant_id); |
| INSERT INTO state_documents_fts(rowid, document_key, body, tenant_id) |
| VALUES (new.rowid, new.document_key, new.body, new.tenant_id); |
| END; |
|
|
| |
| CREATE VIRTUAL TABLE IF NOT EXISTS reference_documents_fts USING fts5( |
| doc_key, body, tenant_id UNINDEXED, |
| content='reference_documents', content_rowid='rowid', |
| tokenize = 'porter unicode61' |
| ); |
|
|
| CREATE TRIGGER IF NOT EXISTS reference_ai_fts |
| AFTER INSERT ON reference_documents BEGIN |
| INSERT INTO reference_documents_fts(rowid, doc_key, body, tenant_id) |
| VALUES (new.rowid, new.doc_key, new.body, new.tenant_id); |
| END; |
|
|
| CREATE TRIGGER IF NOT EXISTS reference_ad_fts |
| AFTER DELETE ON reference_documents BEGIN |
| INSERT INTO reference_documents_fts(reference_documents_fts, rowid, doc_key, body, tenant_id) |
| VALUES ('delete', old.rowid, old.doc_key, old.body, old.tenant_id); |
| END; |
|
|
| CREATE TRIGGER IF NOT EXISTS reference_au_fts |
| AFTER UPDATE ON reference_documents BEGIN |
| INSERT INTO reference_documents_fts(reference_documents_fts, rowid, doc_key, body, tenant_id) |
| VALUES ('delete', old.rowid, old.doc_key, old.body, old.tenant_id); |
| INSERT INTO reference_documents_fts(rowid, doc_key, body, tenant_id) |
| VALUES (new.rowid, new.doc_key, new.body, new.tenant_id); |
| END; |
|
|
| |
| |
| |
| |
| |
| |
| CREATE VIRTUAL TABLE IF NOT EXISTS journal_events_fts USING fts5( |
| ts UNINDEXED, payload, tenant_id UNINDEXED, event_id UNINDEXED, |
| tokenize = 'porter unicode61' |
| ); |
|
|
| CREATE TRIGGER IF NOT EXISTS journal_events_ai_fts |
| AFTER INSERT ON journal_events BEGIN |
| INSERT INTO journal_events_fts(rowid, ts, payload, tenant_id, event_id) |
| VALUES ( |
| new.rowid, new.ts, |
| COALESCE(new.evaluated, '') || ' ' || COALESCE(new.acted, '') || ' ' || |
| COALESCE(new.forward, '') || ' ' || COALESCE(new.extra, ''), |
| new.tenant_id, new.id |
| ); |
| END; |
|
|
| |
| |
| |
| CREATE TABLE IF NOT EXISTS sibyl_memory_schema_version ( |
| version INTEGER PRIMARY KEY, |
| applied_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')), |
| description TEXT |
| ); |
|
|
| INSERT OR IGNORE INTO sibyl_memory_schema_version (version, description) |
| VALUES (1, 'sibyl-memory-client v1. SQLite port of sibyl_memory.* Postgres schema. 10 tables (entities, entity_relations, state_documents, journal_events, revenue_events, error_events, reference_documents, archived_entities, flagged_actors, schema_version) + 2 FTS5 virtual tables. Local-first plugin foundation.'); |
|
|
| |
| |
| |
| |
| |
| |
| |
| CREATE TABLE IF NOT EXISTS skill_proposals ( |
| id TEXT PRIMARY KEY, |
| tenant_id TEXT NOT NULL, |
| created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')), |
|
|
| |
| pattern_kind TEXT NOT NULL, |
| proposed_slug TEXT NOT NULL, |
| proposed_title TEXT, |
| proposed_body TEXT NOT NULL, |
|
|
| |
| evidence TEXT NOT NULL CHECK (json_valid(evidence)), |
| confidence REAL NOT NULL CHECK (confidence >= 0 AND confidence <= 1), |
| summarizer TEXT NOT NULL, |
|
|
| |
| status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'accepted', 'rejected', 'superseded')), |
| reviewed_at TEXT, |
| review_note TEXT, |
|
|
| |
| accepted_doc_key TEXT |
| ); |
|
|
| CREATE INDEX IF NOT EXISTS skill_proposals_tenant_status |
| ON skill_proposals (tenant_id, status, created_at DESC); |
| CREATE INDEX IF NOT EXISTS skill_proposals_slug |
| ON skill_proposals (tenant_id, proposed_slug); |
|
|
| |
| |
| |
| CREATE TABLE IF NOT EXISTS learning_runs ( |
| id TEXT PRIMARY KEY, |
| tenant_id TEXT NOT NULL, |
| started_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')), |
| completed_at TEXT, |
| summarizer TEXT NOT NULL, |
| events_scanned INTEGER NOT NULL DEFAULT 0, |
| proposals_made INTEGER NOT NULL DEFAULT 0, |
| cursor_after_ts TEXT, |
| notes TEXT |
| ); |
|
|
| CREATE INDEX IF NOT EXISTS learning_runs_tenant |
| ON learning_runs (tenant_id, started_at DESC); |
|
|
| INSERT OR IGNORE INTO sibyl_memory_schema_version (version, description) |
| VALUES (2, 'sibyl-memory-client v2. Adds skill_proposals (self-learning review queue) and learning_runs (detector watermark log). Idempotent migration; v1 databases auto-upgrade on first open. Free tier uses local-deterministic summarizer; paid tier can opt into BYOK or Venice/x402-routed summarization.'); |
|
|
| INSERT OR IGNORE INTO sibyl_memory_schema_version (version, description) |
| VALUES (3, 'sibyl-memory-client v3. External-content FTS5 across entities + state_documents + reference_documents + contentless FTS5 over journal_events. Fixes the v0.3.0 "search covers warm entities only" bug. Eliminates body duplication (v2 stored body twice — base table + FTS5). v2 to v3 migration handled in storage.py:_migrate_to_v3: drops the standalone FTS5 tables and rebuilds in external-content shape from existing base-table data. No data loss.'); |
|
|