CREATE TABLE IF NOT EXISTS knowledge_classification_jobs ( id VARCHAR(36) PRIMARY KEY, tenant_id BIGINT NOT NULL, owner_id VARCHAR(36) NOT NULL, knowledge_base_id VARCHAR(36) NOT NULL, model_id VARCHAR(36) NOT NULL, status TEXT NOT NULL DEFAULT 'running', total INTEGER NOT NULL DEFAULT 0, processed INTEGER NOT NULL DEFAULT 0, failed INTEGER NOT NULL DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_classification_owner ON knowledge_classification_jobs(tenant_id,owner_id,knowledge_base_id,created_at DESC); CREATE UNIQUE INDEX IF NOT EXISTS idx_classification_active ON knowledge_classification_jobs(tenant_id,owner_id,knowledge_base_id) WHERE status='running'; CREATE TABLE IF NOT EXISTS knowledge_classification_items ( id VARCHAR(36) PRIMARY KEY, job_id VARCHAR(36) NOT NULL REFERENCES knowledge_classification_jobs(id) ON DELETE CASCADE, knowledge_id VARCHAR(36) NOT NULL, title TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'pending', fingerprint TEXT NOT NULL DEFAULT '', suggestions JSONB NOT NULL DEFAULT '[]', error TEXT NOT NULL DEFAULT '', lease_token VARCHAR(36) NOT NULL DEFAULT '', lease_until TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), UNIQUE(job_id,knowledge_id) ); CREATE INDEX IF NOT EXISTS idx_classification_pending ON knowledge_classification_items(status,lease_until,created_at); CREATE INDEX IF NOT EXISTS idx_classification_job ON knowledge_classification_items(job_id,created_at);