-- Voxyz Autonomous Architecture - Phase 10 Database Schema -- Creates tables for Proposal Service, Policy System, Trigger Rules, and Daily Missions -- Enable UUID extension CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- ============================================ -- 1. MISSION PROPOSALS TABLE -- Stores AI-generated daily mission proposals -- ============================================ CREATE TABLE IF NOT EXISTS ops_mission_proposals ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), -- Proposal metadata proposal_date DATE NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'rejected', 'scheduled', 'completed', 'expired')), -- Priority scoring (0-100) priority_score INTEGER NOT NULL DEFAULT 50 CHECK (priority_score >= 0 AND priority_score <= 100), -- Cap Gates compliance passes_cap_gates BOOLEAN NOT NULL DEFAULT false, cap_gate_violations JSONB DEFAULT '[]'::jsonb, -- Source task references (links to gantt tasks) source_task_ids TEXT[] DEFAULT '{}', source_project_ids TEXT[] DEFAULT '{}', -- Proposal content title TEXT NOT NULL, description TEXT, rationale TEXT, -- AI analysis summary ai_analysis JSONB DEFAULT '{}'::jsonb, -- Scheduling suggested_start_time TIMESTAMP WITH TIME ZONE, suggested_end_time TIMESTAMP WITH TIME ZONE, estimated_duration_minutes INTEGER, -- User decisions approved_at TIMESTAMP WITH TIME ZONE, approved_by UUID REFERENCES users(id), rejected_at TIMESTAMP WITH TIME ZONE, rejection_reason TEXT, -- Calendar integration calendar_event_id TEXT, calendar_synced_at TIMESTAMP WITH TIME ZONE, -- Execution tracking executed_at TIMESTAMP WITH TIME ZONE, execution_notes TEXT, -- Timestamps for lifecycle expires_at TIMESTAMP WITH TIME ZONE NOT NULL, -- Indexes CONSTRAINT valid_dates CHECK (suggested_end_time > suggested_start_time OR suggested_start_time IS NULL) ); -- Create indexes for mission_proposals CREATE INDEX IF NOT EXISTS idx_proposals_status ON ops_mission_proposals(status); CREATE INDEX IF NOT EXISTS idx_proposals_date ON ops_mission_proposals(proposal_date); CREATE INDEX IF NOT EXISTS idx_proposals_priority ON ops_mission_proposals(priority_score DESC); CREATE INDEX IF NOT EXISTS idx_proposals_created_at ON ops_mission_proposals(created_at DESC); -- ============================================ -- 2. POLICY TABLE -- Stores operational policies and constraints -- ============================================ CREATE TABLE IF NOT EXISTS ops_policy ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), -- Policy metadata name VARCHAR(100) NOT NULL UNIQUE, description TEXT, category VARCHAR(50) NOT NULL CHECK (category IN ('cap_gates', 'scheduling', 'prioritization', 'execution', 'general')), -- Policy configuration config JSONB NOT NULL DEFAULT '{}'::jsonb, -- Policy rules (stored as JSON for flexibility) rules JSONB NOT NULL DEFAULT '{}'::jsonb, -- Status is_active BOOLEAN NOT NULL DEFAULT true, effective_from TIMESTAMP WITH TIME ZONE DEFAULT NOW(), effective_until TIMESTAMP WITH TIME ZONE, -- Versioning version INTEGER NOT NULL DEFAULT 1, previous_version_id UUID REFERENCES ops_policy(id), -- Audit created_by UUID REFERENCES users(id), updated_by UUID REFERENCES users(id) ); -- Create indexes for policy CREATE INDEX IF NOT EXISTS idx_policy_category ON ops_policy(category); CREATE INDEX IF NOT EXISTS idx_policy_active ON ops_policy(is_active) WHERE is_active = true; -- ============================================ -- 3. TRIGGER RULES TABLE -- Stores automated trigger rules for the system -- ============================================ CREATE TABLE IF NOT EXISTS ops_trigger_rules ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), -- Rule metadata name VARCHAR(100) NOT NULL, description TEXT, -- Trigger type trigger_type VARCHAR(50) NOT NULL CHECK (trigger_type IN ('deadline_approaching', 'task_blocked', 'high_priority_created', 'stale_task', 'sprint_ending', 'milestone_reached', 'daily_mission_time', 'manual', 'calendar_conflict')), -- Trigger conditions (JSON for complex conditions) conditions JSONB NOT NULL DEFAULT '{}'::jsonb, -- Action to take when triggered action_type VARCHAR(50) NOT NULL CHECK (action_type IN ('create_proposal', 'send_notification', 'escalate_priority', 'auto_schedule', 'request_review', 'update_status')), action_config JSONB NOT NULL DEFAULT '{}'::jsonb, -- Priority for rule evaluation order priority INTEGER NOT NULL DEFAULT 100, -- Status is_active BOOLEAN NOT NULL DEFAULT true, -- Rate limiting cooldown_minutes INTEGER DEFAULT 60, max_triggers_per_day INTEGER DEFAULT 10, -- Tracking last_triggered_at TIMESTAMP WITH TIME ZONE, trigger_count INTEGER DEFAULT 0, -- Audit created_by UUID REFERENCES users(id), updated_by UUID REFERENCES users(id) ); -- Create indexes for trigger_rules CREATE INDEX IF NOT EXISTS idx_trigger_rules_type ON ops_trigger_rules(trigger_type); CREATE INDEX IF NOT EXISTS idx_trigger_rules_active ON ops_trigger_rules(is_active) WHERE is_active = true; CREATE INDEX IF NOT EXISTS idx_trigger_rules_priority ON ops_trigger_rules(priority); -- ============================================ -- 4. CAP GATES TABLE -- Stores queue management cap gates -- ============================================ CREATE TABLE IF NOT EXISTS ops_cap_gates ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), -- Gate metadata name VARCHAR(100) NOT NULL UNIQUE, description TEXT, -- Gate type gate_type VARCHAR(50) NOT NULL CHECK (gate_type IN ('daily_mission_limit', 'concurrent_high_priority', 'workload_capacity', 'focus_time_minimum', 'calendar_buffer', 'reaction_ratio')), -- Configuration max_value INTEGER NOT NULL, min_value INTEGER DEFAULT 0, unit VARCHAR(20) DEFAULT 'count', -- Current state current_value INTEGER DEFAULT 0, last_evaluated_at TIMESTAMP WITH TIME ZONE, -- Policy reference policy_id UUID REFERENCES ops_policy(id), -- Status is_active BOOLEAN NOT NULL DEFAULT true, is_blocking BOOLEAN NOT NULL DEFAULT false, -- Evaluation window evaluation_window_hours INTEGER DEFAULT 24, -- Audit created_by UUID REFERENCES users(id), updated_by UUID REFERENCES users(id) ); -- Create indexes for cap_gates CREATE INDEX IF NOT EXISTS idx_cap_gates_type ON ops_cap_gates(gate_type); CREATE INDEX IF NOT EXISTS idx_cap_gates_active ON ops_cap_gates(is_active) WHERE is_active = true; -- ============================================ -- 5. DAILY MISSIONS TABLE -- Stores generated and scheduled daily missions -- ============================================ CREATE TABLE IF NOT EXISTS ops_daily_missions ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), -- Mission date mission_date DATE NOT NULL, -- Generation metadata generated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), generated_by VARCHAR(50) DEFAULT 'ai_agent' CHECK (generated_by IN ('ai_agent', 'manual', 'trigger')), -- Mission status status VARCHAR(20) NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'review', 'approved', 'scheduled', 'in_progress', 'completed', 'canceled')), -- Proposal references (up to 3 missions per day) primary_mission_id UUID REFERENCES ops_mission_proposals(id), secondary_mission_id UUID REFERENCES ops_mission_proposals(id), tertiary_mission_id UUID REFERENCES ops_mission_proposals(id), -- Total estimated time total_estimated_minutes INTEGER, -- Focus time allocation focus_time_start TIMESTAMP WITH TIME ZONE, focus_time_end TIMESTAMP WITH TIME ZONE, focus_time_minutes INTEGER, -- Calendar blocks calendar_blocks JSONB DEFAULT '[]'::jsonb, -- Reaction matrix tracking planned_reactions INTEGER DEFAULT 0, actual_reactions INTEGER DEFAULT 0, reaction_ratio DECIMAL(3,2) DEFAULT 0.00, -- Completion tracking completed_at TIMESTAMP WITH TIME ZONE, completion_notes TEXT, completion_rating INTEGER CHECK (completion_rating >= 1 AND completion_rating <= 5), -- Feedback for AI learning user_feedback JSONB DEFAULT '{}'::jsonb, -- Unique constraint for one mission set per day CONSTRAINT unique_daily_mission UNIQUE (mission_date) ); -- Create indexes for daily_missions CREATE INDEX IF NOT EXISTS idx_daily_missions_date ON ops_daily_missions(mission_date); CREATE INDEX IF NOT EXISTS idx_daily_missions_status ON ops_daily_missions(status); -- ============================================ -- 6. CALENDAR BLOCKS TABLE -- Stores scheduled focus time blocks -- ============================================ CREATE TABLE IF NOT EXISTS ops_calendar_blocks ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), -- Block metadata block_date DATE NOT NULL, -- Time range start_time TIMESTAMP WITH TIME ZONE NOT NULL, end_time TIMESTAMP WITH TIME ZONE NOT NULL, -- Block type block_type VARCHAR(50) NOT NULL CHECK (block_type IN ('deep_work', 'mission_execution', 'planning', 'reaction_time', 'buffer', 'meeting')), -- Linked mission mission_id UUID REFERENCES ops_daily_missions(id), proposal_id UUID REFERENCES ops_mission_proposals(id), -- External calendar integration calendar_event_id TEXT, calendar_provider VARCHAR(20) DEFAULT 'google' CHECK (calendar_provider IN ('google', 'outlook', 'apple', 'other')), calendar_synced BOOLEAN DEFAULT false, calendar_synced_at TIMESTAMP WITH TIME ZONE, -- Status status VARCHAR(20) DEFAULT 'scheduled' CHECK (status IN ('scheduled', 'active', 'completed', 'canceled', 'rescheduled')), -- Notes notes TEXT, CONSTRAINT valid_block_times CHECK (end_time > start_time) ); -- Create indexes for calendar_blocks CREATE INDEX IF NOT EXISTS idx_calendar_blocks_date ON ops_calendar_blocks(block_date); CREATE INDEX IF NOT EXISTS idx_calendar_blocks_mission ON ops_calendar_blocks(mission_id); CREATE INDEX IF NOT EXISTS idx_calendar_blocks_status ON ops_calendar_blocks(status); -- ============================================ -- 7. TRIGGER LOG TABLE -- Stores trigger rule execution history -- ============================================ CREATE TABLE IF NOT EXISTS ops_trigger_log ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), -- Trigger reference rule_id UUID REFERENCES ops_trigger_rules(id), rule_name VARCHAR(100), -- Execution details triggered_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), trigger_type VARCHAR(50) NOT NULL, -- Context context JSONB DEFAULT '{}'::jsonb, task_ids TEXT[] DEFAULT '{}', -- Result action_taken VARCHAR(50), action_result TEXT, success BOOLEAN DEFAULT true, error_message TEXT, -- Proposal created (if applicable) proposal_id UUID REFERENCES ops_mission_proposals(id) ); -- Create indexes for trigger_log CREATE INDEX IF NOT EXISTS idx_trigger_log_rule ON ops_trigger_log(rule_id); CREATE INDEX IF NOT EXISTS idx_trigger_log_created ON ops_trigger_log(created_at DESC); CREATE INDEX IF NOT EXISTS idx_trigger_log_type ON ops_trigger_log(trigger_type); -- ============================================ -- 8. AGENT EXECUTION LOG TABLE -- Stores AI agent execution history -- ============================================ CREATE TABLE IF NOT EXISTS ops_agent_execution_log ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), -- Execution metadata agent_name VARCHAR(50) NOT NULL CHECK (agent_name IN ('proposal_generator', 'cap_gate_validator', 'calendar_scheduler', 'trigger_monitor', 'mission_optimizer', 'stale_task_detector')), execution_type VARCHAR(50) NOT NULL CHECK (execution_type IN ('scheduled', 'triggered', 'manual', 'reaction')), -- Execution details started_at TIMESTAMP WITH TIME ZONE NOT NULL, completed_at TIMESTAMP WITH TIME ZONE, duration_ms INTEGER, -- Input/Output input_summary JSONB DEFAULT '{}'::jsonb, output_summary JSONB DEFAULT '{}'::jsonb, -- Results proposals_created INTEGER DEFAULT 0, proposals_approved INTEGER DEFAULT 0, tasks_analyzed INTEGER DEFAULT 0, -- Status status VARCHAR(20) DEFAULT 'running' CHECK (status IN ('running', 'success', 'partial', 'failed')), error_message TEXT, -- Performance metrics ai_tokens_used INTEGER, ai_cost_usd DECIMAL(10,4) ); -- Create indexes for agent_execution_log CREATE INDEX IF NOT EXISTS idx_agent_log_agent ON ops_agent_execution_log(agent_name); CREATE INDEX IF NOT EXISTS idx_agent_log_created ON ops_agent_execution_log(created_at DESC); CREATE INDEX IF NOT EXISTS idx_agent_log_status ON ops_agent_execution_log(status); -- ============================================ -- DEFAULT POLICY INSERTS -- ============================================ -- Insert default Cap Gates policies INSERT INTO ops_policy (name, description, category, config, rules) VALUES ('daily_mission_limit', 'Maximum number of missions per day', 'cap_gates', '{"max_missions_per_day": 3, "min_missions_per_day": 1}'::jsonb, '{"enforce": true, "allow_override": false}'::jsonb), ('concurrent_high_priority', 'Limit on concurrent high-priority work', 'cap_gates', '{"max_concurrent_high_priority": 2, "high_priority_threshold": 75}'::jsonb, '{"enforce": true, "escalation_required": true}'::jsonb), ('workload_capacity', 'Daily workload capacity in minutes', 'cap_gates', '{"max_daily_minutes": 480, "min_focus_block_minutes": 90}'::jsonb, '{"enforce": true, "buffer_percentage": 20}'::jsonb), ('focus_time_minimum', 'Minimum required focus time per day', 'cap_gates', '{"min_focus_minutes": 120, "preferred_focus_start": "09:00", "preferred_focus_end": "17:00"}'::jsonb, '{"enforce": true, "auto_protect": true}'::jsonb), ('calendar_buffer', 'Buffer time between calendar events', 'cap_gates', '{"min_buffer_minutes": 15, "default_buffer_minutes": 30}'::jsonb, '{"enforce": true, "auto_add_buffer": true}'::jsonb), ('reaction_ratio', 'Percentage of time reserved for spontaneous reactions', 'cap_gates', '{"reaction_ratio": 0.30, "min_reaction_minutes": 60}'::jsonb, '{"enforce": false, "track_only": true}'::jsonb); -- Insert default Trigger Rules INSERT INTO ops_trigger_rules (name, description, trigger_type, conditions, action_type, action_config, priority) VALUES ('deadline_approaching_24h', 'Trigger when deadline is within 24 hours', 'deadline_approaching', '{"hours_before": 24, "priority": "high"}'::jsonb, 'create_proposal', '{"priority_boost": 20, "rationale_template": "Deadline approaching in {{hours}} hours"}'::jsonb, 100), ('deadline_approaching_72h', 'Trigger when deadline is within 72 hours', 'deadline_approaching', '{"hours_before": 72, "priority": "medium"}'::jsonb, 'create_proposal', '{"priority_boost": 10, "rationale_template": "Deadline approaching in {{hours}} hours"}'::jsonb, 90), ('task_blocked_24h', 'Trigger when task has been blocked for 24+ hours', 'task_blocked', '{"blocked_hours": 24}'::jsonb, 'create_proposal', '{"action": "escalate_and_propose_alternative", "priority_boost": 30}'::jsonb, 95), ('high_priority_created', 'Trigger when high priority task is created', 'high_priority_created', '{"priority": "urgent"}'::jsonb, 'create_proposal', '{"immediate_review": true, "priority_boost": 25}'::jsonb, 110), ('stale_task_7d', 'Trigger when task is stale for 7+ days', 'stale_task', '{"stale_days": 7, "status_in": ["todo", "in-progress"]}'::jsonb, 'create_proposal', '{"action": "review_and_reprioritize", "priority_boost": 15}'::jsonb, 80), ('stale_task_14d', 'Trigger when task is stale for 14+ days', 'stale_task', '{"stale_days": 14, "status_in": ["todo", "in-progress"]}'::jsonb, 'create_proposal', '{"action": "flag_for_review", "priority_boost": 25}'::jsonb, 85), ('sprint_ending_3d', 'Trigger when sprint ends in 3 days', 'sprint_ending', '{"days_before": 3}'::jsonb, 'create_proposal', '{"focus": "sprint_completion", "priority_boost": 20}'::jsonb, 88), ('daily_mission_generation', 'Trigger daily mission generation at 7 AM', 'daily_mission_time', '{"hour": 7, "minute": 0}'::jsonb, 'create_proposal', '{"generate_count": 3, "include_reactions": true}'::jsonb, 120); -- Insert default Cap Gates INSERT INTO ops_cap_gates (name, description, gate_type, max_value, min_value, unit, policy_id) VALUES ('daily_mission_count', 'Maximum missions per day', 'daily_mission_limit', 3, 1, 'count', (SELECT id FROM ops_policy WHERE name = 'daily_mission_limit')), ('concurrent_high_priority', 'Concurrent high priority items', 'concurrent_high_priority', 2, 0, 'count', (SELECT id FROM ops_policy WHERE name = 'concurrent_high_priority')), ('daily_workload', 'Daily workload capacity', 'workload_capacity', 480, 240, 'minutes', (SELECT id FROM ops_policy WHERE name = 'workload_capacity')), ('daily_focus_time', 'Minimum daily focus time', 'focus_time_minimum', 480, 120, 'minutes', (SELECT id FROM ops_policy WHERE name = 'focus_time_minimum')), ('reaction_time_reserve', 'Time reserved for reactions', 'reaction_ratio', 144, 60, 'minutes', (SELECT id FROM ops_policy WHERE name = 'reaction_ratio')); -- Create updated_at trigger function CREATE OR REPLACE FUNCTION update_updated_at_column() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ language 'plpgsql'; -- Create updated_at triggers for all tables CREATE TRIGGER update_ops_mission_proposals_updated_at BEFORE UPDATE ON ops_mission_proposals FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_ops_policy_updated_at BEFORE UPDATE ON ops_policy FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_ops_trigger_rules_updated_at BEFORE UPDATE ON ops_trigger_rules FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_ops_cap_gates_updated_at BEFORE UPDATE ON ops_cap_gates FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_ops_daily_missions_updated_at BEFORE UPDATE ON ops_daily_missions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_ops_calendar_blocks_updated_at BEFORE UPDATE ON ops_calendar_blocks FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();