-- GTD schema. Applied idempotently by migrate step in entrypoint. create table if not exists projects ( id uuid primary key default gen_random_uuid(), name text not null, status text not null default 'active' check (status in ('active', 'someday', 'completed', 'dropped')), notes text not null default '', sort_order double precision not null default 0, created_at timestamptz not null default now(), updated_at timestamptz not null default now() ); create table if not exists tasks ( id uuid primary key default gen_random_uuid(), title text not null, notes text not null default '', -- The GTD lists. 'scheduled' = calendar/tickler items surfaced by defer_date. status text not null default 'inbox' check (status in ('inbox', 'next', 'waiting', 'scheduled', 'someday', 'done', 'trashed')), project_id uuid references projects(id) on delete set null, context text, -- '@home', '@computer', '@errands', '@calls', ... waiting_for text, -- who/what is being waited on when status = 'waiting' due_date date, defer_date date, -- hide from lists until this date priority int not null default 4 check (priority between 1 and 4), -- 1=urgent … 4=low estimate_min int check (estimate_min > 0), repeat text check (repeat in ('daily', 'weekdays', 'weekly', 'monthly', 'yearly')), completed_at timestamptz, sort_order double precision not null default 0, created_at timestamptz not null default now(), updated_at timestamptz not null default now() ); create index if not exists tasks_status_idx on tasks (status); create index if not exists tasks_project_idx on tasks (project_id); -- Columns added after the initial deploy (create-if-not-exists won't alter). alter table tasks add column if not exists repeat text check (repeat in ('daily', 'weekdays', 'weekly', 'monthly', 'yearly'));