116 lines
4.8 KiB
Markdown
116 lines
4.8 KiB
Markdown
---
|
|
source: raw/schema.sql
|
|
content_hash: 71b47e47b483834c887de14c76d5b16506d90ad64198d76a92a7b3731132dab8
|
|
namespace: work
|
|
last_synced: 2026-05-30
|
|
confidence: 0.9
|
|
tags: [personal-os, postgres, schema, asana]
|
|
---
|
|
|
|
# Personal OS — Postgres Schema
|
|
|
|
The Personal OS Postgres database holds Asana sync state, agent annotations,
|
|
file references for wiki ingest, the LLM-synthesised wiki, and a semantic
|
|
memory store. Extensions required: `vector` (pgvector) and `pg_trgm`.
|
|
|
|
## Core Asana tables
|
|
|
|
### `tasks`
|
|
One row per Asana task GID; upserted on every sync. Tracks identity, due
|
|
dates, completion, assignee, project, and a `source` enum that records how
|
|
the task was discovered:
|
|
- `my_tasks` — assigned to me, lives in a My Tasks section
|
|
- `following` — I'm a follower (commented, CC'd)
|
|
- `delegated` — I created it, someone else owns it
|
|
- `project` — visible via a project I'm on, none of the above
|
|
|
|
Bookkeeping columns: `fetched_at`, `stories_fetched_before` (cursor used so
|
|
we only pull new stories), `raw_json` (fallback for unmodeled fields).
|
|
Indexes cover `modified_at`, `due_on` (partial — incomplete only),
|
|
`assignee_gid`, `source`, `completed`, and a trigram index on `name` for
|
|
fuzzy match.
|
|
|
|
### `stories`
|
|
Raw Asana event log per task. The key resource subtypes are
|
|
`comment_added`, `assigned`, `due_date_changed`, `section_changed`,
|
|
`dependency_added`, `attachment_added`, `marked_complete`. Both plain text
|
|
and raw HTML are stored — HTML is needed to extract embedded task GIDs.
|
|
|
|
### `task_edges`
|
|
Directed graph of relationships between tasks. `relation_type` covers
|
|
`subtask`, `dependency` (blocked by), `dependent` (blocking), `project_sibling`,
|
|
and `mention` (referenced inside a story). `related_gid` may not yet
|
|
exist in `tasks`, so it's not a FK.
|
|
|
|
### `task_annotations`
|
|
Agent-written notes about tasks. `annotation_type` is one of `irrelevant`,
|
|
`watching`, `needs_action`, `snoozed`. `annotated_by` is `agent` or `user`.
|
|
|
|
### `sync_state`
|
|
One row per logical sync stream (`my_tasks`, `following`, `delegated`,
|
|
`project:{gid}`, `workspace_events`). Stores `cursor` (ISO timestamp or
|
|
events `sync_token`) and `full_sync_at` so partial syncs can fall back to
|
|
a full pull when needed.
|
|
|
|
### `task_embeddings`
|
|
1024-dim Voyage embedding per task, indexed via HNSW with cosine ops.
|
|
|
|
### `active_tasks` view
|
|
Convenience view: non-completed tasks that aren't annotated `irrelevant`
|
|
or currently snoozed. Ordered by source priority (my_tasks → delegated →
|
|
following → project), then `due_on`, then `modified_at`.
|
|
|
|
## Phase 0 additions (April 2026)
|
|
|
|
All core tables gained a `namespace TEXT NOT NULL DEFAULT 'work'` column —
|
|
the three allowed values are `work`, `personal`, `family`. Applied via
|
|
ALTER TABLE; documented as commented-out statements at the bottom of the
|
|
file for fresh installs.
|
|
|
|
`tasks` also gained `possibly_deleted BOOLEAN` and `last_seen_in_full_sync
|
|
TIMESTAMPTZ` — used by `generate-status.js` to filter out tasks that have
|
|
disappeared from Asana between full syncs.
|
|
|
|
## Wiki + file ingest tables
|
|
|
|
### `file_references`
|
|
Tracks files and URLs that should be ingested into the wiki. Holds a macOS
|
|
security-scoped `bookmark_data` BYTEA, `last_known_path` (resolved
|
|
cache), optional `url`, `content_hash` (SHA256), `mime_type`, `title`, and
|
|
a `modification_log` JSONB of `{ts, hash_before, hash_after}` entries.
|
|
The `wiki_stale` flag drives whether the wiki-ingest prompt processes the
|
|
file on its next run.
|
|
|
|
### `wiki_pages`
|
|
LLM-synthesised wiki content (not raw copies). Columns: `namespace`,
|
|
`title`, `content` (markdown), `sources` JSONB pointing back at
|
|
`file_references`, `confidence`, `superseded_by` (chains old versions),
|
|
`stale`, `last_synced_hash`, and a 1536-dim `embedding`. Tagged for
|
|
ivfflat index but the index is held off until the table has 1000+ rows
|
|
for usable recall.
|
|
|
|
> Note: per Decision 8 in [[personal-os-state-2026-04-27]], the live
|
|
> Personal OS no longer uses these DB tables for wiki ingest — the vault
|
|
> is the source of truth and SHA256 lives in frontmatter. The tables
|
|
> remain in the schema for compatibility / future re-use.
|
|
|
|
### `memory_store`
|
|
Semantic memory accumulated from Discord, Claude sessions, and manual
|
|
entries. `type` ∈ {`fact`, `preference`, `decision`, `person`}; `source` ∈
|
|
{`discord`, `claude`, `manual`}. Includes `entities` JSONB, `confidence`,
|
|
`embedding` (1536), and an optional `expires_at` (NULL = permanent).
|
|
|
|
## Key Points
|
|
|
|
- All namespaces gated to `work | personal | family` via CHECK constraints.
|
|
- pgvector embeddings live on three tables: `task_embeddings`, `wiki_pages`,
|
|
`memory_store`. Only `task_embeddings` ships with an HNSW index;
|
|
the wiki/memory ivfflat indexes are commented out until data volume
|
|
justifies them.
|
|
- The `active_tasks` view is the canonical "what should I look at" surface
|
|
for agents.
|
|
|
|
## Related
|
|
[[personal-os-state-2026-04-27]] [[personal-os-catchup-plan-2026-04-27]]
|
|
[[wiki-ingest-process]] [[ddg-asana-workflow]]
|