Files
Maven/internal/store/schema.sql
claude 8e7aa0d451 nudges: a resolved outcome and a way to close a pending alarm (V-535)
The sev4 repeat path reads the nudges table, so ending an alarm means
writing an ending there. 'resolved' is the daemon closing it because the
condition cleared, which is neither 'acted' nor 'ignored'.

ResolvePendingTelegram is rule-scoped and accepts only the two endings the
daemon may write. OldestPendingTelegram backs the age cap and scans into a
NullInt64, because MIN over an empty set is one NULL row, not zero rows.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 01:42:44 +04:00

86 lines
4.3 KiB
SQL

-- 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,
-- 'resolved' is the daemon closing an alarm because the condition cleared,
-- as opposed to 'acted' (he answered) or 'ignored' (nobody ever did).
outcome TEXT NOT NULL DEFAULT 'pending' CHECK (outcome IN ('pending','acted','snoozed','ignored','resolved')),
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
);