Spaces:
Running
Running
File size: 11,775 Bytes
bd28470 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 | -- ============================================================
-- Migration 002 β Phase 1 Enhancements
-- Territory management, service profiles, social profiles,
-- discovery run tracking, pipeline checkpoints, LLM traces
-- ============================================================
-- βββ SERVICE PROFILES ββββββββββββββββββββββββββββββββββββββββ
-- What services WE offer β what industries β what pain signals to look for
CREATE TABLE service_profiles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
service_name TEXT NOT NULL UNIQUE, -- 'AI Receptionist'
description TEXT,
target_industries TEXT[] NOT NULL, -- ['dental','medical','legal','salon']
min_employees INTEGER DEFAULT 3,
max_employees INTEGER DEFAULT 500,
pain_signals TEXT[] NOT NULL, -- website signals to detect
score_boost INTEGER NOT NULL DEFAULT 15, -- points added when matched
outreach_keywords TEXT[], -- words to use in outreach
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Seed service profiles
INSERT INTO service_profiles (service_name, description, target_industries, min_employees, pain_signals, score_boost, outreach_keywords)
VALUES
('AI Receptionist',
'Automated phone answering, appointment booking, 24/7 availability',
ARRAY['dental','medical','veterinary','legal','salon','spa','real_estate','accounting','chiropractic'],
3,
ARRAY['phone number prominent','book appointment','call us','receptionist','front desk','office hours','schedule a visit'],
20,
ARRAY['missed calls','after hours','appointment booking','front desk costs']),
('AI Customer Support',
'Chatbot, ticket automation, FAQ automation',
ARRAY['ecommerce','saas','retail','hospitality','travel','insurance','telecom'],
10,
ARRAY['contact form','support email','FAQ page','help center','no chatbot','submit a ticket'],
15,
ARRAY['support costs','response time','ticket volume','customer satisfaction']),
('AI Data Processing',
'Document processing, report automation, ERP modernization',
ARRAY['manufacturing','logistics','finance','healthcare','supply_chain','construction','energy'],
50,
ARRAY['legacy ERP','SAP','manual reporting','spreadsheet','data entry','compliance reporting'],
25,
ARRAY['manual processes','reporting overhead','data accuracy','compliance automation']),
('AI Sales Automation',
'Outreach automation, CRM enrichment, lead scoring',
ARRAY['b2b_saas','consulting','recruitment','insurance','financial_services','marketing_agency'],
10,
ARRAY['sales team','CRM','outbound','SDR','BDR','sales development','pipeline'],
20,
ARRAY['pipeline velocity','lead qualification','outbound efficiency','sales productivity']),
('AI Workflow Automation',
'General process automation, integration, workflow optimization',
ARRAY['technology','professional_services','education','media','nonprofit_large','government_contractor'],
20,
ARRAY['manual process','approval workflow','internal tools','legacy system','multiple platforms'],
15,
ARRAY['operational efficiency','process bottlenecks','tool consolidation','workflow speed']);
-- βββ TERRITORY GRID ββββββββββββββββββββββββββββββββββββββββββ
-- Every city Γ industry = one territory unit
CREATE TABLE territory_grid (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
country TEXT NOT NULL,
country_code TEXT NOT NULL,
city TEXT NOT NULL,
tier INTEGER NOT NULL DEFAULT 1, -- 1=major city, 2=mid, 3=small
timezone TEXT, -- 'America/New_York'
is_active BOOLEAN DEFAULT true,
UNIQUE(country_code, city)
);
-- Seed US Tier 1 cities
INSERT INTO territory_grid (country, country_code, city, tier, timezone) VALUES
('United States', 'US', 'New York', 1, 'America/New_York'),
('United States', 'US', 'Los Angeles', 1, 'America/Los_Angeles'),
('United States', 'US', 'Chicago', 1, 'America/Chicago'),
('United States', 'US', 'Houston', 1, 'America/Chicago'),
('United States', 'US', 'Phoenix', 1, 'America/Phoenix'),
('United States', 'US', 'Philadelphia', 1, 'America/New_York'),
('United States', 'US', 'San Antonio', 1, 'America/Chicago'),
('United States', 'US', 'San Diego', 1, 'America/Los_Angeles'),
('United States', 'US', 'Dallas', 1, 'America/Chicago'),
('United States', 'US', 'Austin', 1, 'America/Chicago'),
('United States', 'US', 'San Francisco', 1, 'America/Los_Angeles'),
('United States', 'US', 'Seattle', 1, 'America/Los_Angeles'),
('United States', 'US', 'Denver', 1, 'America/Denver'),
('United States', 'US', 'Boston', 1, 'America/New_York'),
('United States', 'US', 'Miami', 1, 'America/New_York');
-- UK cities
INSERT INTO territory_grid (country, country_code, city, tier, timezone) VALUES
('United Kingdom', 'GB', 'London', 1, 'Europe/London'),
('United Kingdom', 'GB', 'Manchester', 1, 'Europe/London'),
('United Kingdom', 'GB', 'Birmingham', 1, 'Europe/London'),
('United Kingdom', 'GB', 'Leeds', 2, 'Europe/London'),
('United Kingdom', 'GB', 'Edinburgh', 2, 'Europe/London'),
('United Kingdom', 'GB', 'Bristol', 2, 'Europe/London'),
('United Kingdom', 'GB', 'Glasgow', 2, 'Europe/London');
-- Australia cities
INSERT INTO territory_grid (country, country_code, city, tier, timezone) VALUES
('Australia', 'AU', 'Sydney', 1, 'Australia/Sydney'),
('Australia', 'AU', 'Melbourne', 1, 'Australia/Melbourne'),
('Australia', 'AU', 'Brisbane', 1, 'Australia/Brisbane'),
('Australia', 'AU', 'Perth', 2, 'Australia/Perth'),
('Australia', 'AU', 'Adelaide', 2, 'Australia/Adelaide');
-- Gulf cities
INSERT INTO territory_grid (country, country_code, city, tier, timezone) VALUES
('United Arab Emirates', 'AE', 'Dubai', 1, 'Asia/Dubai'),
('United Arab Emirates', 'AE', 'Abu Dhabi', 1, 'Asia/Dubai'),
('Saudi Arabia', 'SA', 'Riyadh', 1, 'Asia/Riyadh'),
('Saudi Arabia', 'SA', 'Jeddah', 2, 'Asia/Riyadh'),
('Qatar', 'QA', 'Doha', 1, 'Asia/Qatar');
-- βββ DISCOVERY RUNS ββββββββββββββββββββββββββββββββββββββββββ
-- Track every search execution β prevents duplicate searches
CREATE TABLE discovery_runs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
run_type TEXT NOT NULL, -- 'auto' | 'manual'
territory_id UUID REFERENCES territory_grid(id),
country_code TEXT NOT NULL,
city TEXT NOT NULL,
industry TEXT NOT NULL,
search_queries TEXT[], -- actual Google queries used
companies_found INTEGER DEFAULT 0,
companies_passed_gate1 INTEGER DEFAULT 0,
companies_passed_gate2 INTEGER DEFAULT 0,
leads_qualified INTEGER DEFAULT 0,
quota_target INTEGER DEFAULT 10,
status TEXT DEFAULT 'running', -- 'running','completed','failed','partial'
triggered_by TEXT DEFAULT 'system', -- 'system' | 'slack:username'
ran_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
completed_at TIMESTAMPTZ
);
CREATE INDEX idx_discovery_runs_territory ON discovery_runs(city, industry, ran_at DESC);
-- βββ TERRITORY PROGRESS βββββββββββββββββββββββββββββββββββββ
-- Tracks which city+industry combos have been covered and when
CREATE TABLE territory_progress (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
territory_id UUID REFERENCES territory_grid(id),
industry TEXT NOT NULL,
last_run_at TIMESTAMPTZ NOT NULL,
next_eligible_at TIMESTAMPTZ NOT NULL, -- last_run + 30 days
total_leads INTEGER DEFAULT 0,
UNIQUE(territory_id, industry)
);
-- βββ PIPELINE CHECKPOINTS βββββββββββββββββββββββββββββββββββ
-- Allows pipeline to resume from failure point (idempotency)
CREATE TABLE pipeline_checkpoints (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
run_id UUID REFERENCES discovery_runs(id),
company_domain TEXT NOT NULL,
stage TEXT NOT NULL, -- 'scraped','filtered','contacts_found','profiled','scored'
stage_data JSONB DEFAULT '{}', -- intermediate data for resume
completed BOOLEAN DEFAULT false,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE(run_id, company_domain)
);
-- βββ LLM CALL TRACES ββββββββββββββββββββββββββββββββββββββββ
-- Every LLM call logged for cost tracking and debugging
CREATE TABLE llm_traces (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
trace_id TEXT NOT NULL, -- pipeline run trace
operation TEXT NOT NULL, -- 'profile','score','email_classify','pain_detect'
model TEXT NOT NULL, -- 'meta/llama-3.3-70b-instruct'
provider TEXT NOT NULL DEFAULT 'nvidia',
prompt_tokens INTEGER,
completion_tokens INTEGER,
total_tokens INTEGER,
latency_ms INTEGER,
success BOOLEAN NOT NULL,
fallback_used BOOLEAN DEFAULT false,
grounding_score NUMERIC(3,2), -- 0.00-1.00 how well grounded
company_id UUID REFERENCES companies(id),
input_hash TEXT, -- hash of prompt (no PII stored)
output_hash TEXT, -- hash of output
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_llm_traces_trace ON llm_traces(trace_id);
CREATE INDEX idx_llm_traces_company ON llm_traces(company_id);
-- βββ SYSTEM CONFIG βββββββββββββββββββββββββββββββββββββββββββ
-- Runtime configuration that Slack commands can modify
CREATE TABLE system_config (
key TEXT PRIMARY KEY,
value JSONB NOT NULL,
updated_by TEXT DEFAULT 'system',
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
INSERT INTO system_config (key, value) VALUES
('daily_quota', '{"default": 10, "today_override": null}'),
('schedule', '{"start_hour_utc": 4, "enabled": true}'),
('auto_mode', '{"enabled": true, "paused": false, "paused_by": null}'),
('current_territory', '{"country_code": "US", "city_index": 0, "industry_index": 0}');
-- βββ ADD SOCIAL PROFILES TO CONTACTS βββββββββββββββββββββββββ
ALTER TABLE contacts ADD COLUMN IF NOT EXISTS linkedin_personal_url TEXT;
ALTER TABLE contacts ADD COLUMN IF NOT EXISTS social_profiles JSONB DEFAULT '{}';
ALTER TABLE contacts ADD COLUMN IF NOT EXISTS email_verification_layers JSONB DEFAULT '{}';
ALTER TABLE contacts ADD COLUMN IF NOT EXISTS email_tier TEXT; -- 'personal','authority','context_verified','rejected'
ALTER TABLE contacts ADD COLUMN IF NOT EXISTS authority_confirmed BOOLEAN DEFAULT false;
-- βββ ADD CITY TO COMPANIES βββββββββββββββββββββββββββββββββββ
ALTER TABLE companies ADD COLUMN IF NOT EXISTS city TEXT;
ALTER TABLE companies ADD COLUMN IF NOT EXISTS service_match TEXT; -- matched service name
ALTER TABLE companies ADD COLUMN IF NOT EXISTS service_match_score INTEGER DEFAULT 0;
ALTER TABLE companies ADD COLUMN IF NOT EXISTS pain_signals TEXT[] DEFAULT '{}';
ALTER TABLE companies ADD COLUMN IF NOT EXISTS trace_id TEXT; -- pipeline trace
|