--- source: raw/schema.sql content_hash: 71b47e47b483834c887de14c76d5b16506d90ad64198d76a92a7b3731132dab8 namespace: work last_synced: 2026-05-29 confidence: 0.9 tags: [schema, postgres, personal-os, database] --- # Personal OS — PostgreSQL Schema The `personal_os` Postgres database is the durable backbone of Alex's Personal OS. It stores Asana state, agent annotations, file references, wiki content, and semantic memory. Extensions used: `vector` (pgvector) and `pg_trgm`. ## Core tables ### `tasks` One row per Asana task GID. Upserted on every sync. Tracks name, notes (text + html), due/start dates, completion state, section, assignee, creator, project, source, timestamps, sync cursors, and raw JSON. Indexed on modified_at, due_on (partial), section, assignee, source, completed, plus a trigram index on name for fuzzy search. **`source` values** — discovery channel: - `my_tasks` — assigned to Alex, in My Tasks sections - `following` — Alex is a follower - `delegated` — Alex created it, someone else owns - `project` — project membership, otherwise uncovered ### `stories` Raw Asana event log per task — comments, assignments, due-date changes, etc. `resource_subtype` is Asana's event type. Stores plain and HTML body (HTML retains embedded task references). Indexed on task_gid, created_at, subtype, creator. ### `task_edges` Directed graph of inter-task relationships. `relation_type` covers `subtask`, `dependency`, `dependent`, `project_sibling`, `mention`. Primary key `(task_gid, related_gid, relation_type)`. ### `task_annotations` Agent or user-written metadata. Types: `irrelevant`, `watching`, `needs_action`, `snoozed`. Includes reasoning note, snooze date, and `annotated_by` (`agent` | `user`). ### `sync_state` One row per logical sync stream (`my_tasks`, `following`, `delegated`, `project:{gid}`, `workspace_events`). Holds last sync time, incremental cursor, and last full-sync time. ### `task_embeddings` pgvector 1024-dim embeddings (Voyage AI text-embedding-3 dims). HNSW cosine index. ## Convenience view `active_tasks` — non-completed, non-irrelevant, non-snoozed tasks. Ordered by `source` priority (`my_tasks` → `delegated` → `following` → `project`), then due date, then modified. ## Wiki / memory tables ### `file_references` Sources for wiki ingest. Includes a macOS security-scoped `bookmark_data` BYTEA, cached path, optional URL, SHA256 `content_hash`, MIME, title, tags, JSONB `modification_log`, and `wiki_stale` flag that triggers next ingest run. Namespace constrained to `work`/`personal`/`family`. ### `wiki_pages` LLM-synthesized markdown (not verbatim copies). Tracks sources JSONB, `confidence` (default 0.8), `superseded_by` chain for versioning, `stale` flag, `last_synced_hash`, and 1536-dim embedding. ivfflat index recommended once row count > 1000. See [[wiki-ingest-process]] for the current file-based replacement that supersedes this table. ### `memory_store` Semantic memory from Discord, Claude sessions, manual entries. `type` ∈ `fact|preference|decision|person`. `source` ∈ `discord|claude|manual`. JSONB entities array, confidence, optional `expires_at` for non-permanent facts, 1536-dim embedding. ## Phase 0 additions (2026-04-27) - `namespace TEXT NOT NULL DEFAULT 'work'` added to all core tables — supports work/personal/family separation. - `possibly_deleted BOOLEAN` and `last_seen_in_full_sync TIMESTAMPTZ` added to `tasks` so sync can detect Asana deletions. ## Notes on usage - Stories are fetched after `tasks.stories_fetched_before` cursor — incremental. - `task_annotations` is the only table the agent writes to from inference — `tasks` and `stories` are sync-owned. - The `wiki_pages` table is effectively superseded by Obsidian + frontmatter `content_hash` (see [[personal-os-state-2026-04-27]] Decision 8). Schema retained for now. ## Key Points - Source-of-truth for Asana state is this DB, not the Asana API at query time. - `source` column on `tasks` drives prioritization in `active_tasks` view. - `namespace` column enables future Phase 2-family without schema churn. - pgvector tables are provisioned but not yet populated — Phase 2 work. - File-references / wiki-pages tables exist but Obsidian vault replaced them in practice. ## Related [[personal-os-state-2026-04-27]] [[personal-os-catchup-plan-2026-04-27]] [[wiki-ingest-process]]