-- maven core schema — append-only, three shapes. -- a wrong fact is superseded, never overwritten. current value = latest non-voided row for a key. PRAGMA journal_mode=WAL; PRAGMA synchronous=NORMAL; PRAGMA foreign_keys=ON; PRAGMA busy_timeout=5000; -- facts — substrate, all observations (self + env + config). -- ts = valid-time (true-as-of), not insert-time. -- source: tap:* | infer:* | poll:* | ambient | promote | feedback -- confidence = 1.0 for taps only; <1 for inferred. -- voids_id points at the fact this one cancels (correction). CREATE TABLE IF NOT EXISTS facts ( id INTEGER PRIMARY KEY AUTOINCREMENT, ts INTEGER NOT NULL, -- unix epoch millis (valid-time) kind TEXT NOT NULL CHECK (kind IN ('self','env','config')), key TEXT NOT NULL, value TEXT NOT NULL, -- json if structured source TEXT NOT NULL, confidence REAL NOT NULL DEFAULT 1.0 CHECK (confidence > 0.0 AND confidence <= 1.0), voids_id INTEGER REFERENCES facts(id) ); CREATE INDEX IF NOT EXISTS idx_facts_key_ts ON facts (key, ts DESC); CREATE INDEX IF NOT EXISTS idx_facts_voids ON facts (voids_id); -- reminders — user intent, fires once or recurring (if cron set). -- relative→absolute happens at capture ("in 4h" → store now+4h, never the string). CREATE TABLE IF NOT EXISTS reminders ( id INTEGER PRIMARY KEY AUTOINCREMENT, created_ts INTEGER NOT NULL, -- epoch millis fire_ts INTEGER NOT NULL, -- epoch millis payload TEXT NOT NULL, -- json status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending','fired','cancelled')) ); CREATE INDEX IF NOT EXISTS idx_reminders_fire ON reminders (fire_ts) WHERE status = 'pending'; CREATE INDEX IF NOT EXISTS idx_reminders_status ON reminders (status); -- nudges — every proactive send + outcome. this table IS the restraint memory. CREATE TABLE IF NOT EXISTS nudges ( id INTEGER PRIMARY KEY AUTOINCREMENT, ts INTEGER NOT NULL, -- sent ts, epoch millis rule TEXT NOT NULL, channel TEXT NOT NULL, message TEXT NOT NULL, outcome TEXT NOT NULL DEFAULT 'pending' CHECK (outcome IN ('pending','acted','snoozed','ignored')), outcome_ts INTEGER ); CREATE INDEX IF NOT EXISTS idx_nudges_rule_ts ON nudges (rule, ts DESC); CREATE INDEX IF NOT EXISTS idx_nudges_outcome ON nudges (outcome); -- notes — semantic recall/preference store. no predicate reads these (that's -- what facts are for); query-answering does brute-force cosine over embedding. -- embedding is a little-endian float32 BLOB. no index — personal-scale scan. CREATE TABLE IF NOT EXISTS notes ( id INTEGER PRIMARY KEY AUTOINCREMENT, ts INTEGER NOT NULL, -- epoch millis text TEXT NOT NULL, embedding BLOB NOT NULL, -- little-endian float32[] source TEXT NOT NULL ); -- tools — the act allowlist maven executes. proposed rows are scaffolds maven -- drafts when she hits an act she can't run; enabling (filling cmd + flipping -- status) is a human act through an authed surface, NEVER the voice path. a -- proposed row drives nothing — the executor only runs status='enabled' rows. CREATE TABLE IF NOT EXISTS tools ( name TEXT PRIMARY KEY, -- the spoken verb ("restart") cmd TEXT NOT NULL DEFAULT '[]', -- json argv prefix; args appended at run destructive INTEGER NOT NULL DEFAULT 0, -- 1 ⇒ needs a confirm turn before it runs status TEXT NOT NULL DEFAULT 'proposed' CHECK (status IN ('proposed','enabled')), utterance TEXT NOT NULL DEFAULT '', -- the utterance that scaffolded a proposal (provenance) created_ts INTEGER NOT NULL, updated_ts INTEGER NOT NULL ); -- presence_state — the only stateful bit of presence (a pure function otherwise). -- hysteresis bucket; updated each tick after resolve(). CREATE TABLE IF NOT EXISTS presence_state ( id INTEGER PRIMARY KEY CHECK (id = 1), -- singleton row last_bucket TEXT NOT NULL CHECK (last_bucket IN ('present','away')), last_score REAL NOT NULL, updated_ts INTEGER NOT NULL );