/** * Federal Preemption Risk & Litigation Tracker - Main Entry Point * * šŸ¦‰ THE COMPLIANCE SENTINEL AI AGENTS TRUST * * Track federal preemption risks and state-federal regulatory friction. * Monitor DOJ, Executive Orders, and federal courts for AI regulation * challenges affecting Colorado SB 24-205, California SB 1047, and * state compliance strategies. * * @author Jason Pellerin AI Solutionist * @see https://jasonpellerin.com */ import { Actor, log } from 'apify'; import { InputSchema, type Input, type PreemptionEvent, type PreemptionReport, type StateConflict } from './utils/types.js'; import { STATE_AI_REGULATIONS } from './utils/types.js'; import { extractExecutiveOrders, extractFederalRegisterDocs } from './extractors/federal-register.js'; import { extractCourtCases } from './extractors/courtlistener.js'; import { extractDojActions, extractWhiteHouseActions } from './extractors/web-sources.js'; import { analyzeStateConflicts } from './analysis/risk-scorer.js'; // Initialize Actor await Actor.init(); // Epic ASCII banner log.info(''); log.info('══════════════════════════════════════════════════════════════════════════════'); log.info(' ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā•— '); log.info(' ā–ˆā–ˆā•”ā•ā•ā•ā•ā•ā–ˆā–ˆā•”ā•ā•ā•ā•ā•ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•—ā–ˆā–ˆā•”ā•ā•ā•ā•ā•ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•—ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•—ā–ˆā–ˆā•‘ '); log.info(' ā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•”ā•ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ '); log.info(' ā–ˆā–ˆā•”ā•ā•ā• ā–ˆā–ˆā•”ā•ā•ā• ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ā–ˆā–ˆā•”ā•ā•ā• ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•—ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ '); log.info(' ā–ˆā–ˆā•‘ ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•”ā•ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—'); log.info(' ā•šā•ā• ā•šā•ā•ā•ā•ā•ā•ā•ā•šā•ā•ā•ā•ā•ā• ā•šā•ā•ā•ā•ā•ā•ā•ā•šā•ā• ā•šā•ā•ā•šā•ā• ā•šā•ā•ā•šā•ā•ā•ā•ā•ā•ā•'); log.info(''); log.info(' ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā•—'); log.info(' ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•—ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•—ā–ˆā–ˆā•”ā•ā•ā•ā•ā•ā–ˆā–ˆā•”ā•ā•ā•ā•ā•ā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā•‘ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•—ā•šā•ā•ā–ˆā–ˆā•”ā•ā•ā•ā–ˆā–ˆā•‘ā–ˆā–ˆā•”ā•ā•ā•ā–ˆā–ˆā•—ā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā•‘'); log.info(' ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•”ā•ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•”ā•ā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā•”ā–ˆā–ˆā–ˆā–ˆā•”ā–ˆā–ˆā•‘ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•”ā• ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ā–ˆā–ˆā•”ā–ˆā–ˆā•— ā–ˆā–ˆā•‘'); log.info(' ā–ˆā–ˆā•”ā•ā•ā•ā• ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•—ā–ˆā–ˆā•”ā•ā•ā• ā–ˆā–ˆā•”ā•ā•ā• ā–ˆā–ˆā•‘ā•šā–ˆā–ˆā•”ā•ā–ˆā–ˆā•‘ā–ˆā–ˆā•”ā•ā•ā•ā• ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ā•šā–ˆā–ˆā•—ā–ˆā–ˆā•‘'); log.info(' ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā•‘ ā•šā•ā• ā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ā•šā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•”ā•ā–ˆā–ˆā•‘ ā•šā–ˆā–ˆā–ˆā–ˆā•‘'); log.info(' ā•šā•ā• ā•šā•ā• ā•šā•ā•ā•šā•ā•ā•ā•ā•ā•ā•ā•šā•ā•ā•ā•ā•ā•ā•ā•šā•ā• ā•šā•ā•ā•šā•ā• ā•šā•ā• ā•šā•ā• ā•šā•ā•ā•ā•ā•ā• ā•šā•ā• ā•šā•ā•ā•ā•'); log.info(''); log.info(' šŸ¦‰ THE COMPLIANCE SENTINEL AI AGENTS TRUST'); log.info(''); log.info(' Tracking Federal Preemption Risks:'); log.info(' āš–ļø Executive Orders & Federal Policy'); log.info(' šŸ›ļø DOJ Enforcement & Guidance'); log.info(' šŸ“œ Federal Court Litigation'); log.info(' šŸ“‹ Federal Register Rules & Notices'); log.info(''); log.info(' Protecting State AI Compliance:'); log.info(' šŸ”ļø Colorado SB 24-205 (CAIA) - Effective June 30, 2026'); log.info(' 🌓 California SB 1047 - Frontier AI Safety'); log.info(' šŸ—½ Connecticut, Illinois, and more...'); log.info('══════════════════════════════════════════════════════════════════════════════'); log.info(''); try { // Get and validate input const rawInput = await Actor.getInput() ?? {}; const input = InputSchema.parse(rawInput) as Input; log.info('šŸŽÆ Configuration:', { searchMode: input.searchMode, targetStates: input.targetStates.join(', '), riskThreshold: input.riskScoreThreshold, maxResults: input.maxResults, outputFormat: input.outputFormat, }); const startTime = Date.now(); const kvStore = await Actor.openKeyValueStore(); // Collect all events let allEvents: PreemptionEvent[] = []; const allErrors: string[] = []; const allWarnings: string[] = []; let totalRequests = 0; // ═══════════════════════════════════════════════════════════════════════════ // Execute based on search mode // ═══════════════════════════════════════════════════════════════════════════ const modes = input.searchMode === 'comprehensive' ? ['executiveOrders', 'federalRegister', 'courtCases', 'dojActions'] : [input.searchMode]; for (const mode of modes) { log.info(`\n═══ Extracting: ${mode} ═══`); switch (mode) { case 'executiveOrders': { if (input.includeExecutiveOrders) { const eoResult = await extractExecutiveOrders(input); allEvents.push(...eoResult.data); allErrors.push(...eoResult.errors); allWarnings.push(...eoResult.warnings); totalRequests += eoResult.metrics.requestCount; log.info(`šŸ“œ Executive Orders: ${eoResult.extracted} extracted`); } break; } case 'federalRegister': { const frResult = await extractFederalRegisterDocs(input); allEvents.push(...frResult.data); allErrors.push(...frResult.errors); allWarnings.push(...frResult.warnings); totalRequests += frResult.metrics.requestCount; log.info(`šŸ“‹ Federal Register: ${frResult.extracted} documents extracted`); break; } case 'courtCases': { const courtResult = await extractCourtCases(input); allEvents.push(...courtResult.data); allErrors.push(...courtResult.errors); allWarnings.push(...courtResult.warnings); totalRequests += courtResult.metrics.requestCount; log.info(`āš–ļø Court Cases: ${courtResult.extracted} cases extracted`); break; } case 'dojActions': { const dojResult = await extractDojActions(input); allEvents.push(...dojResult.data); allErrors.push(...dojResult.errors); totalRequests += dojResult.metrics.requestCount; log.info(`šŸ›ļø DOJ Actions: ${dojResult.extracted} extracted`); const whResult = await extractWhiteHouseActions(input); allEvents.push(...whResult.data); allErrors.push(...whResult.errors); totalRequests += whResult.metrics.requestCount; log.info(`šŸ›ļø White House: ${whResult.extracted} extracted`); break; } case 'stateConflicts': case 'riskAssessment': { // These require all events first - handled below break; } } } // ═══════════════════════════════════════════════════════════════════════════ // Deduplicate and Sort Events // ═══════════════════════════════════════════════════════════════════════════ log.info('\n═══ Processing Results ═══'); // Deduplicate by ID const eventMap = new Map(); for (const event of allEvents) { const existing = eventMap.get(event.id); if (!existing || event.preemptionRisk.score > existing.preemptionRisk.score) { eventMap.set(event.id, event); } } allEvents = Array.from(eventMap.values()); // Sort by risk score (highest first) allEvents.sort((a, b) => b.preemptionRisk.score - a.preemptionRisk.score); log.info(`šŸ“Š Total events after deduplication: ${allEvents.length}`); // ═══════════════════════════════════════════════════════════════════════════ // Analyze State Conflicts // ═══════════════════════════════════════════════════════════════════════════ const conflicts = analyzeStateConflicts(allEvents, input.targetStates); log.info(`šŸ”„ State conflicts identified: ${conflicts.length}`); // ═══════════════════════════════════════════════════════════════════════════ // Generate Report // ═══════════════════════════════════════════════════════════════════════════ const criticalEvents = allEvents.filter(e => e.preemptionRisk.level === 'critical'); const highEvents = allEvents.filter(e => e.preemptionRisk.level === 'high'); // Compile all deadlines const allDeadlines = allEvents .flatMap(e => e.complianceImpact?.deadlines || []) .sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()); const report: PreemptionReport = { title: 'Federal Preemption Risk & Litigation Report', generatedAt: new Date().toISOString(), dateRange: { start: input.dateRangeStart || getDefaultStartDate(), end: input.dateRangeEnd || new Date().toISOString().split('T')[0], }, targetStates: input.targetStates, executiveSummary: { totalEvents: allEvents.length, criticalRisks: criticalEvents.length, highRisks: highEvents.length, activeConflicts: conflicts.length, upcomingDeadlines: allDeadlines.filter(d => new Date(d.date) > new Date()).length, keyFindings: generateKeyFindings(allEvents, conflicts), }, riskDashboard: { overallRiskLevel: criticalEvents.length > 0 ? 'critical' : highEvents.length > 0 ? 'high' : allEvents.length > 0 ? 'medium' : 'low', byState: generateStateRiskSummary(allEvents, conflicts, input.targetStates), bySource: generateSourceSummary(allEvents), }, events: allEvents, conflicts, complianceCalendar: allDeadlines, recommendations: generateRecommendations(allEvents, conflicts), dataQuality: { sourcesQueried: modes.length, successfulQueries: modes.length - allErrors.length, totalResults: allEvents.length, deduplicatedResults: allEvents.length, coverageScore: calculateCoverageScore(allEvents, input), }, }; // ═══════════════════════════════════════════════════════════════════════════ // Output Results // ═══════════════════════════════════════════════════════════════════════════ if (input.outputFormat === 'agent_optimized') { // LLM-optimized format const agentOutput = allEvents.map(e => ({ id: e.id, type: e.eventType, title: e.title, summary: e.summary, riskScore: e.preemptionRisk.score, riskLevel: e.preemptionRisk.level, affectedStates: e.affectedStates, affectedProvisions: e.affectedProvisions, timeline: e.preemptionRisk.timeline, reasoning: e.preemptionRisk.reasoning, recommendedActions: e.complianceImpact?.recommendedActions || [], sourceUrl: e.sourceUrl, datePublished: e.datePublished, ragChunks: e.ragChunks, })); await Actor.pushData(agentOutput); } else if (input.outputFormat === 'summary') { await Actor.pushData([report.executiveSummary]); } else if (input.outputFormat === 'compliance_report') { // Full report with conflicts and recommendations await Actor.pushData([{ ...report, events: allEvents.slice(0, 50), // Limit for report }]); } else { // Detailed - full events await Actor.pushData(allEvents); } // Store full report in key-value store await kvStore.setValue('PREEMPTION_REPORT', report); // Store conflicts separately if (conflicts.length > 0) { await kvStore.setValue('STATE_CONFLICTS', conflicts); } // ═══════════════════════════════════════════════════════════════════════════ // Summary Output // ═══════════════════════════════════════════════════════════════════════════ const duration = Date.now() - startTime; log.info(''); log.info('══════════════════════════════════════════════════════════════════════════════'); log.info(' šŸŽÆ EXTRACTION COMPLETE'); log.info('══════════════════════════════════════════════════════════════════════════════'); log.info(` šŸ“Š Total Events: ${allEvents.length}`); log.info(` 🚨 Critical Risks: ${criticalEvents.length}`); log.info(` āš ļø High Risks: ${highEvents.length}`); log.info(` šŸ”„ State Conflicts: ${conflicts.length}`); log.info(` šŸ“… Upcoming Deadlines: ${allDeadlines.filter(d => new Date(d.date) > new Date()).length}`); log.info(` ⚔ Duration: ${(duration / 1000).toFixed(1)}s`); log.info(` šŸ“” API Requests: ${totalRequests}`); log.info('══════════════════════════════════════════════════════════════════════════════'); if (report.recommendations.length > 0) { log.info(''); log.info('šŸ“‹ TOP RECOMMENDATIONS:'); for (const rec of report.recommendations.slice(0, 5)) { log.info(` → ${rec}`); } } if (criticalEvents.length > 0) { log.info(''); log.info('🚨 CRITICAL RISK EVENTS:'); for (const event of criticalEvents.slice(0, 3)) { log.info(` āš ļø ${event.title.slice(0, 60)}... (Score: ${event.preemptionRisk.score})`); } } log.info(''); log.info('šŸ’” Access detailed report in Key-Value Store → PREEMPTION_REPORT'); log.info('══════════════════════════════════════════════════════════════════════════════'); // Webhook notification for critical risks if (input.webhookUrl && criticalEvents.length > 0) { try { await fetch(input.webhookUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ actorId: Actor.getEnv().actorId, runId: Actor.getEnv().actorRunId, totalEvents: allEvents.length, criticalRisks: criticalEvents.length, highRisks: highEvents.length, conflicts: conflicts.length, status: 'completed', topCritical: criticalEvents.slice(0, 3).map(e => ({ title: e.title, score: e.preemptionRisk.score, url: e.sourceUrl, })), }), }); log.info(`šŸ“¤ Webhook notification sent to ${input.webhookUrl}`); } catch (error) { log.warning(`Webhook notification failed: ${error}`); } } } catch (error) { log.error('Actor failed:', { error: String(error) }); throw error; } finally { await Actor.exit(); } // ═══════════════════════════════════════════════════════════════════════════════ // Helper Functions // ═══════════════════════════════════════════════════════════════════════════════ function getDefaultStartDate(): string { const sixMonthsAgo = new Date(); sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6); return sixMonthsAgo.toISOString().split('T')[0]; } function generateKeyFindings(events: PreemptionEvent[], conflicts: StateConflict[]): string[] { const findings: string[] = []; const criticalCount = events.filter(e => e.preemptionRisk.level === 'critical').length; if (criticalCount > 0) { findings.push(`${criticalCount} critical preemption risk events detected requiring immediate attention`); } // Check for Executive Order 14281 specifically const eo14281 = events.find(e => /14281|Removing Barriers.*AI/i.test(e.title)); if (eo14281) { findings.push('Executive Order 14281 creates federal funding risk for states with "onerous" AI regulations'); } // Check for active litigation const litigation = events.filter(e => e.eventType === 'court_case' || e.eventType === 'preemption_challenge'); if (litigation.length > 0) { findings.push(`${litigation.length} active federal court cases may impact state AI regulation validity`); } // State-specific findings const coConflicts = conflicts.filter(c => c.stateRegulation.state === 'CO'); if (coConflicts.length > 0) { findings.push(`Colorado SB 24-205 faces ${coConflicts.length} potential federal conflicts before June 2026 deadline`); } if (findings.length === 0) { findings.push('No critical preemption risks detected in current scan period'); } return findings; } function generateStateRiskSummary( events: PreemptionEvent[], conflicts: StateConflict[], targetStates: string[] ): { state: string; riskScore: number; trend: 'increasing' | 'stable' | 'decreasing' }[] { return targetStates .filter(s => s !== 'ALL') .map(state => { const stateEvents = events.filter(e => e.affectedStates.includes(state)); const stateConflicts = conflicts.filter(c => c.stateRegulation.state === state); // Calculate average risk score const avgScore = stateEvents.length > 0 ? Math.round(stateEvents.reduce((sum, e) => sum + e.preemptionRisk.score, 0) / stateEvents.length) : 25; // Add conflict penalty const conflictPenalty = Math.min(stateConflicts.length * 10, 30); return { state, riskScore: Math.min(avgScore + conflictPenalty, 100), trend: 'stable' as const, // Would need historical data to determine trend }; }); } function generateSourceSummary(events: PreemptionEvent[]): { source: import('./utils/types.js').FederalAuthority; count: number; avgRisk: number }[] { const bySource = new Map(); for (const event of events) { const existing = bySource.get(event.federalAuthority) || { count: 0, totalRisk: 0 }; existing.count++; existing.totalRisk += event.preemptionRisk.score; bySource.set(event.federalAuthority, existing); } return Array.from(bySource.entries()) .map(([source, data]) => ({ source, count: data.count, avgRisk: Math.round(data.totalRisk / data.count), })) .sort((a, b) => b.avgRisk - a.avgRisk); } function generateRecommendations(events: PreemptionEvent[], conflicts: StateConflict[]): string[] { const recommendations: string[] = []; const criticalEvents = events.filter(e => e.preemptionRisk.level === 'critical'); const highEvents = events.filter(e => e.preemptionRisk.level === 'high'); if (criticalEvents.length > 0) { recommendations.push('URGENT: Convene legal review of critical preemption risks within 7 days'); recommendations.push('Document current compliance posture for potential "reasonable care" defense'); } if (conflicts.some(c => c.stateRegulation.state === 'CO')) { recommendations.push('Review Colorado SB 24-205 compliance timeline against federal developments'); recommendations.push('Consider ISO/IEC 42001 certification to strengthen affirmative defense position'); } const fundingThreats = events.filter(e => e.preemptionRisk.basis.includes('federal_funding_threat') ); if (fundingThreats.length > 0) { recommendations.push('Inventory federal grants and broadband funding at risk from EO 14281'); recommendations.push('Evaluate cost-benefit of maintaining state compliance vs. federal alignment'); } const pendingCases = events.filter(e => e.eventType === 'court_case'); if (pendingCases.length > 0) { recommendations.push('Monitor pending federal litigation for precedent-setting decisions'); recommendations.push('Consider filing amicus brief in key cases affecting state AI regulation'); } // Always include monitoring recommendation recommendations.push('Establish monthly preemption risk monitoring cadence'); recommendations.push('Subscribe to Federal Register alerts for AI-related rulemaking'); return recommendations; } function calculateCoverageScore(events: PreemptionEvent[], input: Input): number { let score = 50; // Base score // Bonus for multiple sources const sources = new Set(events.map(e => e.source)); score += Math.min(sources.size * 10, 30); // Bonus for court coverage if (events.some(e => e.eventType === 'court_case' || e.eventType === 'court_opinion')) { score += 10; } // Bonus for executive order coverage if (events.some(e => e.eventType === 'executive_order')) { score += 10; } return Math.min(score, 100); }