diff --git a/AUTOMATION-IMPLEMENTATION-PLAN-COMPLETE.md b/AUTOMATION-IMPLEMENTATION-PLAN-COMPLETE.md
deleted file mode 100644
index 44af3e0f..00000000
--- a/AUTOMATION-IMPLEMENTATION-PLAN-COMPLETE.md
+++ /dev/null
@@ -1,1185 +0,0 @@
-# AI Automation Pipeline - Implementation Blueprint
-**Date:** December 3, 2025
-**Purpose:** Site-level automation orchestrating existing AI functions into sequential 7-stage pipeline
-
----
-
-## 🎯 EXECUTIVE SUMMARY
-
-### What We're Building
-A **site-level automation page** (`/automation`) that orchestrates 6 existing AI functions + 1 local function into a **strictly sequential** 7-stage pipeline for hands-free content generation from keywords to draft content ready for review.
-
-### Core Principles
-✅ **Zero Duplication** - Reuse all existing AI functions (auto_cluster, generate_ideas, generate_content, generate_image_prompts, generate_images)
-✅ **Strictly Sequential** - Stage N+1 ONLY starts when Stage N is 100% complete
-✅ **Batch Processing** - Within each stage, process items in configurable batches with queues visible
-✅ **Site-Level Scope** - NO sector filtering - operates on entire site's data
-✅ **Observable** - Real-time batch progress, detailed queue counts, stage-by-stage logs
-✅ **Safe Execution** - Distributed locks, credit reservations, idempotent stages, Celery task chaining
-
-### Sequential Stage Execution
-- **Stage completes** → Trigger next stage automatically
-- **Within stage** → Process batches sequentially until queue empty
-- **Between stages** → Hard stop, verify completion, then proceed
-- **Never parallel** - Only 1 stage active at a time per site
-
-### Automation Stops Before Publishing
-- **Stage 7 (Manual Review Gate)** - Automation ends when content is draft+images ready
-- User manually reviews and publishes via existing bulk actions
-- No automated publishing to WordPress (human oversight required)
-
----
-
-## 🏗️ SCOPE & DATA MODEL
-
-### Site-Level Operation (NO Sector)
-```
-┌─────────────────────────────────────┐
-│ Site: "example.com" │
-│ ├─ Keywords (ALL sectors combined) │
-│ ├─ Clusters (ALL sectors combined) │
-│ ├─ Ideas (ALL sectors combined) │
-│ └─ Tasks (ALL sectors combined) │
-└─────────────────────────────────────┘
-
-UI: Only Site selector at top
-Database queries: Filter by site_id only
-No sector dropdown in automation page
-```
-
-### Why Site-Level?
-- **Simplicity** - User manages automation per website, not per topic
-- **Unified Progress** - See total content pipeline for entire site
-- **Flexible Sectors** - Content can span multiple sectors naturally
-- **Easier Scheduling** - One automation config per site
-
----
-
-## 📋 EXISTING AI FUNCTIONS (Reused, Not Duplicated)
-
-| Function | File | Input | Output | Credits | Already Works |
-|----------|------|-------|--------|---------|---------------|
-| **auto_cluster** | `ai/functions/auto_cluster.py` | Keyword IDs (max 20) | Clusters created | 1 per 5 keywords | ✅ Yes |
-| **generate_ideas** | `ai/functions/generate_ideas.py` | Cluster IDs (max 5) | Ideas created | 2 per cluster | ✅ Yes |
-| **generate_content** | `ai/functions/generate_content.py` | Task IDs (1 at a time) | Content draft | 1 per 500 words | ✅ Yes |
-| **generate_image_prompts** | `ai/functions/generate_image_prompts.py` | Content IDs | Image prompts | 0.5 per prompt | ✅ Yes |
-| **generate_images** | `ai/functions/generate_images.py` | Image prompt IDs | Generated images | 1-4 per image | ✅ Yes |
-| **bulk_queue_to_writer** | `modules/planner/views.py#L1084` | Idea IDs | Tasks created | 0 (local) | ✅ Yes |
-
-**All functions already:**
-- Have async Celery tasks
-- Return task_id for progress tracking
-- Deduct credits automatically
-- Update model statuses (new → mapped → queued → completed)
-- Handle errors gracefully
-
----
-
-## 🏗️ NEW COMPONENTS TO BUILD
-
-### Phase 1: Backend Infrastructure
-
-#### 1.1 Database Models
-**File:** `backend/igny8_core/business/automation/models.py`
-
-```python
-class AutomationRun(SiteSectorBaseModel):
- """Track each automation run"""
- run_id = models.CharField(max_length=100, unique=True, db_index=True)
- # Format: run_20251203_140523_manual or run_20251204_020000_scheduled
-
- trigger_type = models.CharField(max_length=20, choices=[
- ('manual', 'Manual'),
- ('scheduled', 'Scheduled')
- ])
-
- status = models.CharField(max_length=20, choices=[
- ('running', 'Running'),
- ('paused', 'Paused'),
- ('completed', 'Completed'),
- ('failed', 'Failed')
- ], default='running')
-
- current_stage = models.IntegerField(default=1) # 1-7
-
- started_at = models.DateTimeField(auto_now_add=True)
- completed_at = models.DateTimeField(null=True, blank=True)
-
- total_credits_used = models.IntegerField(default=0)
-
- # Stage results (JSON)
- stage_1_result = models.JSONField(default=dict, blank=True) # {clusters_created: 8, keywords_processed: 47}
- stage_2_result = models.JSONField(default=dict, blank=True) # {ideas_created: 56}
- stage_3_result = models.JSONField(default=dict, blank=True) # {tasks_created: 56}
- stage_4_result = models.JSONField(default=dict, blank=True) # {content_created: 56}
- stage_5_result = models.JSONField(default=dict, blank=True) # {prompts_created: 224}
- stage_6_result = models.JSONField(default=dict, blank=True) # {images_created: 224}
- stage_7_result = models.JSONField(default=dict, blank=True) # {ready_for_review: 56}
-
- error_message = models.TextField(blank=True, null=True)
-
- class Meta:
- ordering = ['-started_at']
- indexes = [
- models.Index(fields=['run_id']),
- models.Index(fields=['site', 'sector', '-started_at']),
- ]
-
-
-class AutomationConfig(SiteSectorBaseModel):
- """Store automation schedule and settings per site/sector"""
-
- is_enabled = models.BooleanField(default=False)
-
- # Schedule
- frequency = models.CharField(max_length=20, choices=[
- ('daily', 'Daily'),
- ('weekly', 'Weekly'),
- ('monthly', 'Monthly')
- ], default='daily')
-
- scheduled_time = models.TimeField(default='02:00') # 2:00 AM
-
- # Batch sizes (sensible defaults from plan)
- stage_1_batch_size = models.IntegerField(default=20) # Keywords per batch
- stage_2_batch_size = models.IntegerField(default=1) # Clusters at a time
- stage_3_batch_size = models.IntegerField(default=20) # Ideas per batch
- stage_4_batch_size = models.IntegerField(default=1) # Tasks (sequential)
- stage_5_batch_size = models.IntegerField(default=1) # Content at a time
- stage_6_batch_size = models.IntegerField(default=1) # Images (auto-handled)
-
- last_run_at = models.DateTimeField(null=True, blank=True)
- next_run_at = models.DateTimeField(null=True, blank=True)
-
- class Meta:
- unique_together = [['site', 'sector']]
-```
-
-#### 1.2 Logging Service
-**File:** `backend/igny8_core/business/automation/services/automation_logger.py`
-
-```python
-import os
-import logging
-from datetime import datetime
-from django.conf import settings
-
-class AutomationLogger:
- """File-based logging for automation runs"""
-
- def __init__(self):
- self.base_path = os.path.join(settings.BASE_DIR, 'logs', 'automation')
-
- def start_run(self, account_id, site_id, sector_id, trigger_type):
- """Create run_id and log directory"""
- timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
- run_id = f"run_{timestamp}_{trigger_type}"
-
- # Create directory: logs/automation/{account_id}/{site_id}/{sector_id}/{run_id}/
- log_dir = os.path.join(
- self.base_path,
- str(account_id),
- str(site_id),
- str(sector_id),
- run_id
- )
- os.makedirs(log_dir, exist_ok=True)
-
- # Create main log file
- main_log = os.path.join(log_dir, 'automation_run.log')
- with open(main_log, 'w') as f:
- f.write(f"{'='*60}\\n")
- f.write(f"AUTOMATION RUN: {run_id}\\n")
- f.write(f"Started: {datetime.now()}\\n")
- f.write(f"Trigger: {trigger_type}\\n")
- f.write(f"{'='*60}\\n\\n")
-
- return run_id
-
- def log_stage_start(self, run_id, stage_number, stage_name, pending_count, account_id, site_id, sector_id):
- """Log start of a stage"""
- stage_file = self._get_stage_file(run_id, stage_number, account_id, site_id, sector_id)
- timestamp = datetime.now().strftime('%H:%M:%S')
-
- with open(stage_file, 'a') as f:
- f.write(f"\\n{'='*60}\\n")
- f.write(f"STAGE {stage_number}: {stage_name}\\n")
- f.write(f"Started: {datetime.now()}\\n")
- f.write(f"{'='*60}\\n\\n")
- f.write(f"{timestamp} - Found {pending_count} items to process\\n")
-
- def log_stage_progress(self, run_id, stage_number, message, account_id, site_id, sector_id):
- """Log progress within a stage"""
- stage_file = self._get_stage_file(run_id, stage_number, account_id, site_id, sector_id)
- timestamp = datetime.now().strftime('%H:%M:%S')
-
- with open(stage_file, 'a') as f:
- f.write(f"{timestamp} - {message}\\n")
-
- # Also append to main log
- main_file = self._get_main_log(run_id, account_id, site_id, sector_id)
- with open(main_file, 'a') as f:
- f.write(f"{timestamp} - Stage {stage_number}: {message}\\n")
-
- def log_stage_complete(self, run_id, stage_number, stage_name, processed_count, time_elapsed, credits_used, account_id, site_id, sector_id):
- """Log completion of a stage"""
- stage_file = self._get_stage_file(run_id, stage_number, account_id, site_id, sector_id)
-
- with open(stage_file, 'a') as f:
- f.write(f"\\n{'='*60}\\n")
- f.write(f"STAGE {stage_number} COMPLETE\\n")
- f.write(f"Total Time: {time_elapsed}\\n")
- f.write(f"Processed: {processed_count} items\\n")
- f.write(f"Credits Used: {credits_used}\\n")
- f.write(f"{'='*60}\\n")
-
- def log_stage_error(self, run_id, stage_number, error_message, account_id, site_id, sector_id):
- """Log error in a stage"""
- stage_file = self._get_stage_file(run_id, stage_number, account_id, site_id, sector_id)
- timestamp = datetime.now().strftime('%H:%M:%S')
-
- with open(stage_file, 'a') as f:
- f.write(f"\\n{timestamp} - ERROR: {error_message}\\n")
-
- def get_activity_log(self, run_id, account_id, site_id, sector_id, last_n=50):
- """Get last N lines from main log"""
- main_file = self._get_main_log(run_id, account_id, site_id, sector_id)
-
- if not os.path.exists(main_file):
- return []
-
- with open(main_file, 'r') as f:
- lines = f.readlines()
- return lines[-last_n:] # Last 50 lines
-
- def _get_stage_file(self, run_id, stage_number, account_id, site_id, sector_id):
- """Get path to stage log file"""
- log_dir = os.path.join(
- self.base_path,
- str(account_id),
- str(site_id),
- str(sector_id),
- run_id
- )
- return os.path.join(log_dir, f"stage_{stage_number}.log")
-
- def _get_main_log(self, run_id, account_id, site_id, sector_id):
- """Get path to main log file"""
- log_dir = os.path.join(
- self.base_path,
- str(account_id),
- str(site_id),
- str(sector_id),
- run_id
- )
- return os.path.join(log_dir, 'automation_run.log')
-```
-
-#### 1.3 Automation Service (Core Orchestrator)
-**File:** `backend/igny8_core/business/automation/services/automation_service.py`
-
-```python
-import time
-from datetime import datetime, timedelta
-from django.utils import timezone
-from igny8_core.business.automation.models import AutomationRun, AutomationConfig
-from igny8_core.business.automation.services.automation_logger import AutomationLogger
-from igny8_core.business.planning.models import Keywords, Clusters, ContentIdeas
-from igny8_core.business.content.models import Tasks, Content, Images
-from igny8_core.business.billing.services.credit_service import CreditService
-
-# Import existing services (NO DUPLICATION)
-from igny8_core.business.planning.services.clustering_service import ClusteringService
-from igny8_core.business.planning.services.ideas_service import IdeasService
-from igny8_core.ai.functions.generate_content import GenerateContentFunction
-from igny8_core.ai.functions.generate_image_prompts import GenerateImagePromptsFunction
-from igny8_core.ai.functions.generate_images import GenerateImagesFunction
-
-
-class AutomationService:
- """
- Orchestrates the 7-stage automation pipeline.
- Reuses all existing AI functions - zero duplication.
- """
-
- def __init__(self, account, site, sector):
- self.account = account
- self.site = site
- self.sector = sector
- self.logger = AutomationLogger()
- self.credit_service = CreditService()
-
- # Existing services
- self.clustering_service = ClusteringService()
- self.ideas_service = IdeasService()
- self.content_function = GenerateContentFunction()
- self.prompts_function = GenerateImagePromptsFunction()
- self.images_function = GenerateImagesFunction()
-
- self.run = None
- self.config = None
-
- def start_automation(self, trigger_type='manual'):
- \"\"\"
- Main entry point for automation.
- Creates run record, executes stages sequentially.
- \"\"\"
- try:
- # Create run record
- run_id = self.logger.start_run(
- self.account.id,
- self.site.id,
- self.sector.id,
- trigger_type
- )
-
- self.run = AutomationRun.objects.create(
- run_id=run_id,
- trigger_type=trigger_type,
- account=self.account,
- site=self.site,
- sector=self.sector,
- status='running',
- current_stage=1
- )
-
- # Load config (for batch sizes)
- self.config = AutomationConfig.objects.filter(
- site=self.site,
- sector=self.sector
- ).first()
-
- if not self.config:
- # Create default config
- self.config = AutomationConfig.objects.create(
- site=self.site,
- sector=self.sector,
- account=self.account
- )
-
- # Execute stages sequentially
- self.run_stage_1() # Keywords → Clusters
- self.run_stage_2() # Clusters → Ideas
- self.run_stage_3() # Ideas → Tasks
- self.run_stage_4() # Tasks → Content
- self.run_stage_5() # Content → Image Prompts
- self.run_stage_6() # Image Prompts → Images
- self.run_stage_7() # Manual Review Gate
-
- # Mark complete
- self.run.status = 'completed'
- self.run.completed_at = timezone.now()
- self.run.save()
-
- return {
- 'success': True,
- 'run_id': run_id,
- 'message': 'Automation completed successfully'
- }
-
- except Exception as e:
- if self.run:
- self.run.status = 'failed'
- self.run.error_message = str(e)
- self.run.save()
-
- return {
- 'success': False,
- 'error': str(e)
- }
-
- def run_stage_1(self):
- \"\"\"Stage 1: Keywords (status='new') → Clusters (AI)\"\"\"
- stage_start = time.time()
- stage_number = 1
- stage_name = "Keywords → Clusters (AI)"
-
- # Find pending keywords (status='new', cluster_id=null)
- pending_keywords = Keywords.objects.filter(
- site=self.site,
- sector=self.sector,
- status='new',
- cluster__isnull=True,
- disabled=False
- )
-
- total_count = pending_keywords.count()
-
- if total_count == 0:
- self.logger.log_stage_progress(
- self.run.run_id, stage_number,
- "No pending keywords found - skipping stage",
- self.account.id, self.site.id, self.sector.id
- )
- self.run.current_stage = 2
- self.run.save()
- return
-
- self.logger.log_stage_start(
- self.run.run_id, stage_number, stage_name, total_count,
- self.account.id, self.site.id, self.sector.id
- )
-
- # Process in batches (default 20 per batch)
- batch_size = self.config.stage_1_batch_size
- keyword_ids = list(pending_keywords.values_list('id', flat=True))
-
- clusters_created = 0
- keywords_processed = 0
- credits_used = 0
-
- for i in range(0, len(keyword_ids), batch_size):
- batch = keyword_ids[i:i+batch_size]
- batch_num = (i // batch_size) + 1
- total_batches = (len(keyword_ids) + batch_size - 1) // batch_size
-
- self.logger.log_stage_progress(
- self.run.run_id, stage_number,
- f"Processing batch {batch_num}/{total_batches} ({len(batch)} keywords)",
- self.account.id, self.site.id, self.sector.id
- )
-
- # Call existing ClusteringService (REUSE - NO DUPLICATION)
- result = self.clustering_service.cluster_keywords(
- keyword_ids=batch,
- account=self.account,
- sector_id=self.sector.id
- )
-
- if result.get('success'):
- clusters_created += result.get('clusters_created', 0)
- keywords_processed += len(batch)
- credits_used += result.get('credits_used', 0)
-
- self.logger.log_stage_progress(
- self.run.run_id, stage_number,
- f"Batch {batch_num} complete: {result.get('clusters_created', 0)} clusters created",
- self.account.id, self.site.id, self.sector.id
- )
-
- # Save stage result
- elapsed = time.time() - stage_start
- self.run.stage_1_result = {
- 'clusters_created': clusters_created,
- 'keywords_processed': keywords_processed
- }
- self.run.total_credits_used += credits_used
- self.run.current_stage = 2
- self.run.save()
-
- self.logger.log_stage_complete(
- self.run.run_id, stage_number, stage_name,
- keywords_processed, f"{elapsed:.0f}s", credits_used,
- self.account.id, self.site.id, self.sector.id
- )
-
- def run_stage_2(self):
- \"\"\"Stage 2: Clusters (status='new', no ideas) → Ideas (AI)\"\"\"
- # Similar structure to stage_1
- # Calls existing IdeasService.generate_ideas()
- pass
-
- def run_stage_3(self):
- \"\"\"Stage 3: Ideas (status='new') → Tasks (Local queue)\"\"\"
- # Calls existing bulk_queue_to_writer endpoint logic
- pass
-
- def run_stage_4(self):
- \"\"\"Stage 4: Tasks (status='queued') → Content (AI)\"\"\"
- # Calls existing GenerateContentFunction
- # Process one task at a time (sequential)
- pass
-
- def run_stage_5(self):
- \"\"\"Stage 5: Content (draft) → Image Prompts (AI)\"\"\"
- # Calls existing GenerateImagePromptsFunction
- pass
-
- def run_stage_6(self):
- \"\"\"Stage 6: Image Prompts (pending) → Images (AI)\"\"\"
- # Calls existing GenerateImagesFunction
- # Handles batching automatically
- pass
-
- def run_stage_7(self):
- \"\"\"Stage 7: Manual Review Gate (STOP)\"\"\"
- # Just count content ready for review
- # Log final status
- # Automation ends here
- pass
-```
-
----
-
-### Phase 2: API Endpoints
-
-#### 2.1 Automation ViewSet
-**File:** `backend/igny8_core/modules/automation/views.py` (NEW MODULE)
-
-```python
-from rest_framework import viewsets
-from rest_framework.decorators import action
-from igny8_core.api.base import SiteSectorModelViewSet
-from igny8_core.api.response import success_response, error_response
-from igny8_core.business.automation.models import AutomationRun, AutomationConfig
-from igny8_core.business.automation.services.automation_service import AutomationService
-from igny8_core.business.automation.services.automation_logger import AutomationLogger
-
-class AutomationViewSet(SiteSectorModelViewSet):
- """API endpoints for automation"""
-
- @action(detail=False, methods=['post'])
- def run_now(self, request):
- """Trigger manual automation run"""
- account = request.account
- site = request.site
- sector = request.sector
-
- # Start automation
- service = AutomationService(account, site, sector)
- result = service.start_automation(trigger_type='manual')
-
- if result['success']:
- return success_response(data={'run_id': result['run_id']})
- else:
- return error_response(message=result['error'])
-
- @action(detail=False, methods=['get'])
- def current_run(self, request):
- """Get current/latest automation run status"""
- site = request.site
- sector = request.sector
-
- run = AutomationRun.objects.filter(
- site=site,
- sector=sector
- ).order_by('-started_at').first()
-
- if not run:
- return success_response(data={'run': None})
-
- # Get activity log
- logger = AutomationLogger()
- activity = logger.get_activity_log(
- run.run_id,
- run.account_id,
- run.site_id,
- run.sector_id,
- last_n=50
- )
-
- return success_response(data={
- 'run': {
- 'run_id': run.run_id,
- 'status': run.status,
- 'current_stage': run.current_stage,
- 'trigger_type': run.trigger_type,
- 'started_at': run.started_at,
- 'total_credits_used': run.total_credits_used,
- 'stage_1_result': run.stage_1_result,
- 'stage_2_result': run.stage_2_result,
- 'stage_3_result': run.stage_3_result,
- 'stage_4_result': run.stage_4_result,
- 'stage_5_result': run.stage_5_result,
- 'stage_6_result': run.stage_6_result,
- 'stage_7_result': run.stage_7_result,
- },
- 'activity_log': activity
- })
-
- @action(detail=False, methods=['get', 'put'])
- def config(self, request):
- """Get/Update automation configuration"""
- site = request.site
- sector = request.sector
- account = request.account
-
- if request.method == 'GET':
- config, created = AutomationConfig.objects.get_or_create(
- site=site,
- sector=sector,
- defaults={'account': account}
- )
-
- return success_response(data={
- 'is_enabled': config.is_enabled,
- 'frequency': config.frequency,
- 'scheduled_time': config.scheduled_time,
- 'next_run_at': config.next_run_at,
- 'stage_1_batch_size': config.stage_1_batch_size,
- 'stage_2_batch_size': config.stage_2_batch_size,
- 'stage_3_batch_size': config.stage_3_batch_size,
- 'stage_4_batch_size': config.stage_4_batch_size,
- 'stage_5_batch_size': config.stage_5_batch_size,
- 'stage_6_batch_size': config.stage_6_batch_size,
- })
-
- elif request.method == 'PUT':
- # Update configuration
- config, created = AutomationConfig.objects.get_or_create(
- site=site,
- sector=sector,
- defaults={'account': account}
- )
-
- # Update fields from request
- config.is_enabled = request.data.get('is_enabled', config.is_enabled)
- config.frequency = request.data.get('frequency', config.frequency)
- config.scheduled_time = request.data.get('scheduled_time', config.scheduled_time)
- config.save()
-
- return success_response(message='Configuration updated')
-```
-
-#### 2.2 URL Configuration
-**File:** `backend/igny8_core/urls/api_urls.py` (ADD)
-
-```python
-# Add to router
-router.register(r'automation', AutomationViewSet, basename='automation')
-```
-
----
-
-### Phase 3: Celery Scheduled Task
-
-#### 3.1 Periodic Task for Scheduled Runs
-**File:** `backend/igny8_core/tasks/automation_tasks.py` (NEW)
-
-```python
-from celery import shared_task
-from django.utils import timezone
-from datetime import datetime, timedelta
-from igny8_core.business.automation.models import AutomationConfig
-from igny8_core.business.automation.services.automation_service import AutomationService
-from igny8_core.auth.models import Account, Site, Sector
-
-@shared_task(name='run_scheduled_automation')
-def run_scheduled_automation():
- \"\"\"
- Celery beat task - runs every hour, checks if any configs need to run
- \"\"\"
- now = timezone.now()
-
- # Find configs that:
- # 1. Are enabled
- # 2. Have next_run_at <= now
- configs = AutomationConfig.objects.filter(
- is_enabled=True,
- next_run_at__lte=now
- )
-
- for config in configs:
- try:
- # Load related objects
- account = config.account
- site = config.site
- sector = config.sector
-
- # Start automation
- service = AutomationService(account, site, sector)
- service.start_automation(trigger_type='scheduled')
-
- # Calculate next run time
- if config.frequency == 'daily':
- next_run = now + timedelta(days=1)
- elif config.frequency == 'weekly':
- next_run = now + timedelta(weeks=1)
- elif config.frequency == 'monthly':
- next_run = now + timedelta(days=30)
-
- # Set time to scheduled_time
- next_run = next_run.replace(
- hour=config.scheduled_time.hour,
- minute=config.scheduled_time.minute,
- second=0,
- microsecond=0
- )
-
- config.last_run_at = now
- config.next_run_at = next_run
- config.save()
-
- except Exception as e:
- # Log error but continue with other configs
- print(f"Error running scheduled automation for {config.id}: {e}")
- continue
-```
-
-#### 3.2 Register Celery Beat Schedule
-**File:** `backend/igny8_core/celery.py` (UPDATE)
-
-```python
-app.conf.beat_schedule = {
- # ... existing schedules ...
- 'run-scheduled-automation': {
- 'task': 'run_scheduled_automation',
- 'schedule': crontab(minute=0), # Every hour on the hour
- },
-}
-```
-
----
-
-### Phase 4: Frontend Components
-
-#### 4.1 Automation Page Component
-**File:** `frontend/src/pages/Automation/Dashboard.tsx` (NEW)
-
-```tsx
-import { useState, useEffect } from 'react';
-import { useInterval } from '../../hooks/useInterval';
-import { automationApi } from '../../services/api/automationApi';
-import { useSiteStore } from '../../stores/siteStore';
-import { useSectorStore } from '../../stores/sectorStore';
-import Button from '../../components/ui/button/Button';
-import { BoltIcon, PlayIcon, PauseIcon, SettingsIcon } from '../../icons';
-import StageCard from './components/StageCard';
-import ActivityLog from './components/ActivityLog';
-import ConfigModal from './components/ConfigModal';
-
-export default function AutomationDashboard() {
- const { activeSite } = useSiteStore();
- const { activeSector } = useSectorStore();
-
- const [currentRun, setCurrentRun] = useState(null);
- const [activityLog, setActivityLog] = useState([]);
- const [config, setConfig] = useState(null);
- const [showConfigModal, setShowConfigModal] = useState(false);
- const [isRunning, setIsRunning] = useState(false);
-
- // Poll current run status every 3 seconds when running
- useInterval(() => {
- if (activeSite && activeSector) {
- loadCurrentRun();
- }
- }, currentRun?.status === 'running' ? 3000 : null);
-
- useEffect(() => {
- if (activeSite && activeSector) {
- loadCurrentRun();
- loadConfig();
- }
- }, [activeSite?.id, activeSector?.id]);
-
- const loadCurrentRun = async () => {
- const response = await automationApi.getCurrentRun();
- if (response.success) {
- setCurrentRun(response.data.run);
- setActivityLog(response.data.activity_log || []);
- }
- };
-
- const loadConfig = async () => {
- const response = await automationApi.getConfig();
- if (response.success) {
- setConfig(response.data);
- }
- };
-
- const handleRunNow = async () => {
- setIsRunning(true);
- const response = await automationApi.runNow();
- if (response.success) {
- // Start polling
- loadCurrentRun();
- }
- setIsRunning(false);
- };
-
- return (
-
- {/* Header */}
-
-
-
-
- AI Automation Pipeline
-
-
- Automated content generation from keywords to review
-
-
-
-
- }
- variant="primary"
- >
- {isRunning ? 'Starting...' : 'Run Now'}
-
-
-
-
-
-
- {/* Schedule Info */}
- {config && (
-
-
-
-
- {config.is_enabled ? '⏰ Scheduled' : '⏸ Paused'}
-
-
- {config.is_enabled
- ? `Next Run: ${config.next_run_at} (${config.frequency})`
- : 'Scheduling disabled'
- }
-
-
-
-
-
- {currentRun?.total_credits_used || 0}
-
-
- Credits Used
-
-
-
-
- )}
-
- {/* Pipeline Overview */}
-
-
Pipeline Overview
-
-
- Keywords
-
- →
-
- Clusters
-
- →
-
- Ideas
-
- →
-
- Tasks
-
- →
-
- Content
-
- →
-
- Review
-
-
-
- {currentRun && (
-
-
-
- Stage {currentRun.current_stage}/7
-
-
- )}
-
-
- {/* Stage Cards */}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {/* Activity Log */}
-
-
- {/* Config Modal */}
- {showConfigModal && (
-
setShowConfigModal(false)}
- config={config}
- onSave={loadConfig}
- />
- )}
-
- );
-}
-
-function getStageStatus(run, stageNumber) {
- if (!run) return 'waiting';
- if (run.status === 'running' && run.current_stage === stageNumber) return 'running';
- if (run.current_stage > stageNumber) return 'completed';
- return 'waiting';
-}
-```
-
-#### 4.2 Add to Sidebar Menu
-**File:** `frontend/src/layouts/AppSidebar.tsx` (UPDATE)
-
-```tsx
-// Add after Sites menu item
-{
- path: '/automation',
- label: 'Automation',
- icon: ,
- badge: automationRunning ? { text: 'Running', color: 'green' } : null
-},
-```
-
-#### 4.3 API Service
-**File:** `frontend/src/services/api/automationApi.ts` (NEW)
-
-```typescript
-import { apiClient } from './apiClient';
-
-export const automationApi = {
- runNow: () => apiClient.post('/automation/run_now/'),
-
- getCurrentRun: () => apiClient.get('/automation/current_run/'),
-
- getConfig: () => apiClient.get('/automation/config/'),
-
- updateConfig: (data: any) => apiClient.put('/automation/config/', data),
-};
-```
-
----
-
-### Phase 5: Implementation Checklist
-
-#### Week 1: Backend Foundation
-- [ ] Create `automation` module directory structure
-- [ ] Implement `AutomationRun` and `AutomationConfig` models
-- [ ] Run migrations
-- [ ] Implement `AutomationLogger` service
-- [ ] Test file logging manually
-
-#### Week 2: Core Service
-- [ ] Implement `AutomationService` class
-- [ ] Implement `run_stage_1()` (Keywords → Clusters)
-- [ ] Test stage 1 in isolation
-- [ ] Implement `run_stage_2()` (Clusters → Ideas)
-- [ ] Test stage 2 in isolation
-- [ ] Implement remaining stages 3-7
-
-#### Week 3: API & Scheduling
-- [ ] Create `AutomationViewSet` with endpoints
-- [ ] Test manual run via API
-- [ ] Implement Celery periodic task
-- [ ] Test scheduled runs
-- [ ] Add error handling and rollback
-
-#### Week 4: Frontend
-- [ ] Create Automation page component
-- [ ] Implement StageCard component
-- [ ] Implement ActivityLog component
-- [ ] Implement ConfigModal component
-- [ ] Add to sidebar menu
-- [ ] Test full UI flow
-
-#### Week 5: Testing & Polish
-- [ ] End-to-end testing (manual + scheduled)
-- [ ] Load testing (100+ keywords)
-- [ ] Credit calculation verification
-- [ ] Log file verification
-- [ ] UI polish and responsiveness
-- [ ] Documentation update
-
----
-
-### Phase 6: Safety Mechanisms
-
-#### 6.1 Pause/Resume
-```python
-# In AutomationService
-def pause_run(self):
- self.run.status = 'paused'
- self.run.save()
-
-def resume_run(self):
- self.run.status = 'running'
- self.run.save()
- # Resume from current_stage
-```
-
-#### 6.2 Rollback on Error
-```python
-# Each stage wraps in try-except
-try:
- self.run_stage_1()
-except Exception as e:
- self.logger.log_stage_error(self.run.run_id, 1, str(e))
- self.run.status = 'failed'
- self.run.error_message = str(e)
- self.run.save()
- # Optionally: rollback created records
- raise
-```
-
-#### 6.3 Credit Pre-Check
-```python
-# Before starting, estimate total credits needed
-def estimate_credits(self):
- keywords = Keywords.objects.filter(status='new', cluster__isnull=True).count()
- clusters = Clusters.objects.filter(ideas__isnull=True).count()
- # ... etc
-
- total_estimate = (keywords / 5) + (clusters * 2) + ...
-
- if self.account.credits_balance < total_estimate:
- raise InsufficientCreditsError(f"Need ~{total_estimate} credits")
-```
-
----
-
-### Phase 7: Monitoring & Observability
-
-#### 7.1 Dashboard Metrics
-- Total runs (today/week/month)
-- Success rate
-- Average credits per run
-- Average time per stage
-- Content pieces generated
-
-#### 7.2 Alerts
-- Email when run completes
-- Email on failure
-- Slack notification (optional)
-
----
-
-## 🎨 UI/UX HIGHLIGHTS
-
-### Rich Visual Design
-- **Stage Cards** with status badges (waiting/running/completed/failed)
-- **Live Progress Bar** for current stage
-- **Activity Feed** with timestamps and color-coded messages
-- **Credit Counter** with real-time updates
-- **Schedule Badge** showing next run time
-
-### User Experience
-- **One-Click Run** - Single "Run Now" button
-- **Real-Time Updates** - Auto-refreshes every 3 seconds when running
-- **Clear Status** - Visual indicators for each stage
-- **Easy Config** - Modal for schedule settings
-- **Error Clarity** - Detailed error messages with stage number
-
----
-
-## 🔧 TROUBLESHOOTING GUIDE
-
-### Issue: Stage stuck in "running"
-**Solution:**
-1. Check `/logs/automation/{account}/{site}/{sector}/{run_id}/stage_X.log`
-2. Look for last log entry
-3. Check Celery worker logs
-4. Manually mark stage complete or restart
-
-### Issue: Credits deducted but no results
-**Solution:**
-1. Check stage log for AI task_id
-2. Query task progress endpoint
-3. Verify AI function completed
-4. Rollback transaction if needed
-
-### Issue: Duplicate clusters created
-**Solution:**
-1. Add unique constraint on cluster name per sector
-2. Check deduplication logic in ClusteringService
-3. Review stage_1 logs for batch processing
-
----
-
-## 📊 SUCCESS METRICS
-
-After implementation, measure:
-- **Automation adoption rate** (% of sites using scheduled runs)
-- **Content generation volume** (pieces per day/week)
-- **Time savings** (manual hours vs automated)
-- **Credit efficiency** (credits per content piece)
-- **Error rate** (failed runs / total runs)
-
----
-
-## 🚀 FUTURE ENHANCEMENTS
-
-### Phase 8: Advanced Features
-- **Conditional stages** (skip if no data)
-- **Parallel processing** (multiple tasks at once in stage 4)
-- **Smart scheduling** (avoid peak hours)
-- **A/B testing** (test different prompts)
-- **Content quality scoring** (auto-reject low scores)
-
-### Phase 9: Integrations
-- **WordPress auto-publish** (with approval workflow)
-- **Analytics tracking** (measure content performance)
-- **Social media posting** (auto-share published content)
-
----
-
-**END OF IMPLEMENTATION PLAN**
-
-This plan provides a complete, production-ready automation system that:
-✅ Reuses all existing AI functions (zero duplication)
-✅ Modular and maintainable (each stage independent)
-✅ Observable and debuggable (file logs + database records)
-✅ Safe and reliable (error handling + rollback)
-✅ Rich UI/UX (real-time updates + visual feedback)
-✅ Scalable (handles 100+ keywords efficiently)
diff --git a/LOGGING-REFERENCE.md b/LOGGING-REFERENCE.md
deleted file mode 100644
index b7e0decd..00000000
--- a/LOGGING-REFERENCE.md
+++ /dev/null
@@ -1,317 +0,0 @@
-# IGNY8 Publish/Sync Logging System
-
-## Overview
-Comprehensive file-based logging system for tracking all WordPress publish/sync workflows with site-specific stamps.
-
-## Log Format
-All logs include site identification stamps in the format: `[site-id-domain]`
-
-Example: `[16-homeg8.com]`
-
----
-
-## Backend Logs (IGNY8 SaaS Platform)
-
-### Location
-```
-/data/app/igny8/backend/logs/publish-sync-logs/
-```
-
-### Log Files
-
-#### 1. `publish-sync.log`
-**Purpose:** Main workflow logging for content publishing
-
-**Contains:**
-- Complete publish workflow from start to finish
-- Step-by-step progress (STEP 1, STEP 2, etc.)
-- Content preparation (categories, tags, images, SEO)
-- Success/failure status
-- Timing information (duration in milliseconds)
-
-**Format:**
-```
-[2025-12-01 00:45:23] [INFO] ================================================================================
-[2025-12-01 00:45:23] [INFO] [16-homeg8.com] 🎯 PUBLISH WORKFLOW STARTED
-[2025-12-01 00:45:23] [INFO] [16-homeg8.com] Content ID: 123
-[2025-12-01 00:45:23] [INFO] [16-homeg8.com] STEP 1: Loading content and integration from database...
-[2025-12-01 00:45:23] [INFO] [16-homeg8.com] ✅ Content loaded: 'Article Title'
-...
-[2025-12-01 00:45:25] [INFO] [16-homeg8.com] 🎉 PUBLISH WORKFLOW COMPLETED SUCCESSFULLY
-```
-
-#### 2. `wordpress-api.log`
-**Purpose:** HTTP API communication with WordPress sites
-
-**Contains:**
-- API requests (method, endpoint, headers, payload)
-- API responses (status code, body)
-- API errors and timeouts
-- Request/response timing
-
-**Format:**
-```
-[2025-12-01 00:45:24] [INFO] [16-homeg8.com] API REQUEST: POST https://homeg8.com/wp-json/igny8/v1/publish
-[2025-12-01 00:45:24] [INFO] [16-homeg8.com] Headers: X-IGNY8-API-Key: ***abcd
-[2025-12-01 00:45:24] [INFO] [16-homeg8.com] Payload: {...}
-[2025-12-01 00:45:25] [INFO] [16-homeg8.com] API RESPONSE: 201
-[2025-12-01 00:45:25] [INFO] [16-homeg8.com] Response body: {"success":true...}
-```
-
-#### 3. `webhooks.log`
-**Purpose:** Webhook events received from WordPress
-
-**Contains:**
-- Webhook POST requests from WordPress
-- Status updates from WordPress to IGNY8
-- Metadata synchronization events
-- Authentication verification
-
-**Format:**
-```
-[2025-12-01 00:45:30] [INFO] [16-homeg8.com] 📥 WORDPRESS STATUS WEBHOOK RECEIVED
-[2025-12-01 00:45:30] [INFO] [16-homeg8.com] Content ID: 123
-[2025-12-01 00:45:30] [INFO] [16-homeg8.com] Post ID: 456
-[2025-12-01 00:45:30] [INFO] [16-homeg8.com] Post Status: publish
-```
-
-### Viewing Backend Logs
-
-```bash
-# View all publish logs
-tail -f /data/app/igny8/backend/logs/publish-sync-logs/publish-sync.log
-
-# View API communication
-tail -f /data/app/igny8/backend/logs/publish-sync-logs/wordpress-api.log
-
-# View webhook events
-tail -f /data/app/igny8/backend/logs/publish-sync-logs/webhooks.log
-
-# Search for specific site
-grep "\[16-homeg8.com\]" /data/app/igny8/backend/logs/publish-sync-logs/publish-sync.log
-
-# Search for errors
-grep "\[ERROR\]" /data/app/igny8/backend/logs/publish-sync-logs/*.log
-
-# View last 100 lines of all logs
-tail -n 100 /data/app/igny8/backend/logs/publish-sync-logs/*.log
-```
-
----
-
-## WordPress Plugin Logs
-
-### Location
-```
-/wp-content/plugins/igny8-ai-os/logs/publish-sync-logs/
-```
-
-On your server:
-```
-/home/u276331481/domains/homeg8.com/public_html/wp-content/plugins/igny8-ai-os/logs/publish-sync-logs/
-```
-
-### Log Files
-
-#### 1. `publish-sync.log`
-**Purpose:** WordPress post creation and synchronization
-
-**Contains:**
-- Post creation workflow
-- Categories/tags assignment
-- Featured image processing
-- SEO metadata updates
-- Gallery image handling
-- Success/failure status
-
-**Format:**
-```
-[2025-12-01 00:45:25] [INFO] ================================================================================
-[2025-12-01 00:45:25] [INFO] [16-homeg8.com] 🎯 CREATE WORDPRESS POST FROM IGNY8
-[2025-12-01 00:45:25] [INFO] [16-homeg8.com] Content ID: 123
-[2025-12-01 00:45:25] [INFO] [16-homeg8.com] STEP: Processing 3 categories
-[2025-12-01 00:45:25] [INFO] [16-homeg8.com] ✅ Assigned 3 categories to post 456
-...
-[2025-12-01 00:45:26] [INFO] [16-homeg8.com] 🎉 POST CREATION COMPLETED SUCCESSFULLY
-```
-
-#### 2. `wordpress-api.log`
-**Purpose:** WordPress outgoing API calls to IGNY8
-
-**Contains:**
-- API requests from WordPress to IGNY8
-- Task updates
-- Status synchronization
-- API responses
-
-#### 3. `webhooks.log`
-**Purpose:** Outgoing webhook calls from WordPress to IGNY8
-
-**Contains:**
-- Status webhook sends
-- Metadata webhook sends
-- Response handling
-
-### Viewing WordPress Logs
-
-```bash
-# On the WordPress server
-cd /home/u276331481/domains/homeg8.com/public_html/wp-content/plugins/igny8-ai-os/logs/publish-sync-logs/
-
-# View all publish logs
-tail -f publish-sync.log
-
-# View API communication
-tail -f wordpress-api.log
-
-# View webhook events
-tail -f webhooks.log
-
-# Search for specific content ID
-grep "Content ID: 123" publish-sync.log
-
-# View last 50 lines
-tail -n 50 publish-sync.log
-```
-
----
-
-## Log Retention
-
-### Automatic Rotation
-- **Max file size:** 10 MB per log file
-- **Backup count:** 10 rotated files kept
-- **Total storage:** ~100 MB per log type (10 files × 10 MB)
-
-### Rotated Files
-```
-publish-sync.log # Current log
-publish-sync.log.1 # Previous rotation
-publish-sync.log.2 # Older rotation
-...
-publish-sync.log.10 # Oldest rotation (auto-deleted when new rotation created)
-```
-
----
-
-## Troubleshooting Guide
-
-### 1. Content Not Publishing
-
-**Check:**
-```bash
-# Backend - Publishing workflow
-grep "PUBLISH WORKFLOW" /data/app/igny8/backend/logs/publish-sync-logs/publish-sync.log | tail -20
-
-# Backend - API errors
-grep "\[ERROR\]" /data/app/igny8/backend/logs/publish-sync-logs/wordpress-api.log | tail -20
-
-# WordPress - Post creation
-tail -50 /wp-content/plugins/igny8-ai-os/logs/publish-sync-logs/publish-sync.log
-```
-
-### 2. Missing Categories/Tags
-
-**Check:**
-```bash
-# WordPress logs - Category processing
-grep "Processing.*categories" /wp-content/plugins/igny8-ai-os/logs/publish-sync-logs/publish-sync.log
-
-# WordPress logs - Tag processing
-grep "Processing.*tags" /wp-content/plugins/igny8-ai-os/logs/publish-sync-logs/publish-sync.log
-```
-
-### 3. Status Not Syncing
-
-**Check:**
-```bash
-# Backend - Webhook reception
-grep "WEBHOOK RECEIVED" /data/app/igny8/backend/logs/publish-sync-logs/webhooks.log | tail -20
-
-# WordPress - Webhook sending
-grep "webhook" /wp-content/plugins/igny8-ai-os/logs/publish-sync-logs/webhooks.log | tail -20
-```
-
-### 4. API Connection Issues
-
-**Check:**
-```bash
-# Backend - API requests/responses
-grep "API REQUEST\|API RESPONSE\|API ERROR" /data/app/igny8/backend/logs/publish-sync-logs/wordpress-api.log | tail -30
-
-# Look for timeouts
-grep "timeout" /data/app/igny8/backend/logs/publish-sync-logs/*.log
-```
-
----
-
-## Common Log Patterns
-
-### Successful Publish
-```
-[INFO] [16-homeg8.com] 🎯 PUBLISH WORKFLOW STARTED
-[INFO] [16-homeg8.com] STEP 1: Loading content...
-[INFO] [16-homeg8.com] STEP 2: Checking if already published...
-[INFO] [16-homeg8.com] STEP 3: Generating excerpt...
-[INFO] [16-homeg8.com] STEP 4: Loading taxonomy mappings...
-[INFO] [16-homeg8.com] STEP 5: Extracting keywords...
-[INFO] [16-homeg8.com] STEP 6: Loading images...
-[INFO] [16-homeg8.com] STEP 7: Building WordPress API payload...
-[INFO] [16-homeg8.com] STEP 8: Sending POST request...
-[INFO] [16-homeg8.com] ✅ WordPress responded: HTTP 201
-[INFO] [16-homeg8.com] STEP 9: Processing WordPress response...
-[INFO] [16-homeg8.com] ✅ WordPress post created successfully
-[INFO] [16-homeg8.com] 🎉 PUBLISH WORKFLOW COMPLETED SUCCESSFULLY
-```
-
-### API Error
-```
-[ERROR] [16-homeg8.com] ❌ Unexpected status code: 500
-[ERROR] [16-homeg8.com] Response: {"code":"internal_server_error"...}
-[ERROR] [16-homeg8.com] API ERROR: WordPress API error: HTTP 500
-```
-
-### Missing Fields
-```
-[WARNING] [16-homeg8.com] ⚠️ No categories in content_data
-[WARNING] [16-homeg8.com] ⚠️ No featured image in content_data
-[WARNING] [16-homeg8.com] ⚠️ No SEO description in content_data
-```
-
----
-
-## Accessing Logs via Debug Page
-
-The frontend Debug Status page will display these logs in real-time (coming next).
-
-**URL:** https://app.igny8.com/settings/debug-status
-
----
-
-## Log Cleanup
-
-### Manual Cleanup
-```bash
-# Backend
-rm -f /data/app/igny8/backend/logs/publish-sync-logs/*.log*
-
-# WordPress (on your server)
-rm -f /home/u276331481/domains/homeg8.com/public_html/wp-content/plugins/igny8-ai-os/logs/publish-sync-logs/*.log*
-```
-
-### Keep Recent Logs Only
-```bash
-# Keep only last 1000 lines
-tail -n 1000 /data/app/igny8/backend/logs/publish-sync-logs/publish-sync.log > /tmp/temp.log
-mv /tmp/temp.log /data/app/igny8/backend/logs/publish-sync-logs/publish-sync.log
-```
-
----
-
-## Notes
-
-- All timestamps are in server local time
-- Site stamps format: `[site-id-domain]`
-- Emoji indicators: 🎯 (start), ✅ (success), ❌ (error), ⚠️ (warning), 🎉 (completion)
-- Logs are written in real-time during publish workflows
-- File rotation happens automatically at 10MB per file
diff --git a/STATUS-UNIFIED-STRUCTURE-PLAN-v2.md b/STATUS-UNIFIED-STRUCTURE-PLAN-v2.md
deleted file mode 100644
index 0cb60ef4..00000000
--- a/STATUS-UNIFIED-STRUCTURE-PLAN-v2.md
+++ /dev/null
@@ -1,541 +0,0 @@
-# Unified Status Structure Plan - Keywords, Clusters, Ideas (CORRECTED)
-
-**Date:** December 3, 2025
-**Objective:** Implement unified, workflow-driven status values across all three modules
-
----
-
-## 🎯 Key Concept: Status vs Workflow
-
-### ✅ WORKFLOW STATUS (Auto-updated by AI/System)
-These statuses represent the workflow progression:
-- Keywords: `new` → `mapped`
-- Clusters: `new` → `mapped`
-- Ideas: `new` → `queued` → `completed`
-
-### 🔘 OPTIONAL MANUAL STATUS (User control only)
-`disabled` = **NOT a workflow step**, but a **filter status**
-- Does NOT affect workflow
-- Manually set by user only
-- Excludes items from all automated processes
-- Excludes from dashboard metrics/suggestions
-- Can be toggled on/off anytime
-
-**Important:** `disabled` is a **data attribute**, not a workflow state. Items with `disabled=true` are simply ignored by all processes.
-
----
-
-## 📋 Module Status Definitions
-
-### KEYWORDS Module
-**Workflow Statuses:** `new` → `mapped`
-**Optional Filter Status:** `disabled` (manual user control)
-
-| Status | Type | Meaning | When Set | Process Behavior |
-|--------|------|---------|----------|-----------------|
-| **new** | Workflow | Keyword attached to site, awaiting cluster assignment | User adds keyword via import/UI | Included in auto-cluster AI suggestions |
-| **mapped** | Workflow | Keyword assigned to a cluster | AI auto_cluster completes or manual cluster assignment | Can be used for idea generation; included in cluster-based workflows |
-| **disabled** | Filter | Manually excluded from processes | User manually sets | Excluded from auto-cluster, idea generation, dashboard (optional) |
-
-**Workflow Transition:**
-```
-new ──[AI auto_cluster]──> mapped
- │
- └──[User toggle]──> disabled (any time, no workflow impact)
-```
-
----
-
-### CLUSTERS Module
-**Workflow Statuses:** `new` → `mapped`
-**Optional Filter Status:** `disabled` (manual user control)
-
-| Status | Type | Meaning | When Set | Process Behavior |
-|--------|------|---------|----------|-----------------|
-| **new** | Workflow | Cluster created; ready for idea generation | AI clustering creates OR user manually creates | Included in auto-generate-ideas suggestions |
-| **mapped** | Workflow | Ideas generated from this cluster | AI generate_ideas completes | Ideas are ready; can be queued to writer |
-| **disabled** | Filter | Manually excluded from processes | User manually sets | Excluded from idea generation, suggestion lists, dashboard (optional) |
-
-**Workflow Transition:**
-```
-new ──[AI generate_ideas]──> mapped
- │
- └──[User toggle]──> disabled (any time, no workflow impact)
-```
-
----
-
-### IDEAS Module
-**Workflow Statuses:** `new` → `queued` → `completed`
-**Optional Filter Status:** `disabled` (manual user control)
-
-| Status | Type | Meaning | When Set | Process Behavior |
-|--------|------|---------|----------|-----------------|
-| **new** | Workflow | Idea generated by AI; awaiting queue to writer | AI generate_ideas creates | Included in bulk-queue suggestions |
-| **queued** | Workflow | Queued to writer; Task record created in Writer module | User bulk-queues ideas to writer | Task is assigned; waiting for content generation |
-| **completed** | Workflow | Content generated from task (tracked via Task.status='completed') | generate_content AI completes; Content record created | Final automated state; content ready for publishing/deployment |
-| **disabled** | Filter | Manually excluded from processes | User manually sets | Excluded from queue suggestions, bulk operations, dashboard (optional) |
-
-**Workflow Transition:**
-```
-new ──[User bulk_queue]──> queued ──[Writer AI: generate_content]──> completed
- │
- └──[User toggle]──> disabled (any time, no workflow impact)
-```
-
-**Note on `completed`:**
-- When a Task's status becomes `completed`, the related Idea automatically becomes `completed`
-- No separate `published` status needed; publishing is a separate content deployment action
-- One idea = one content piece through task tracking
-
----
-
-## 🔄 Process Exclusion Rules
-
-### When `disabled=true` (filter status):
-Items are **excluded from**:
-- ✗ AI process suggestions (auto-cluster, generate-ideas)
-- ✗ Bulk operation selections (queue to writer, generate content)
-- ✗ Dashboard workflow metrics (unless explicitly shown)
-- ✗ Progress calculations (% mapped, % queued, etc.)
-
-### When workflow status applies:
-- ✅ Included in relevant processes
-- ✅ Included in dashboard metrics
-- ✅ Included in AI suggestions
-- ✅ Can be bulk-operated on
-
----
-
-## 📊 Status Update Flow
-
-```
-═══ KEYWORDS WORKFLOW ═══
-1. User imports SeedKeywords
- └─> Keywords created with status='new'
-
-2. Auto-cluster AI runs
- └─> Keywords assigned to clusters
- └─> Keywords status changes to 'mapped'
-
-3. [Optional] User manually disables keyword
- └─> Keywords.disabled = true
- └─> Excluded from all processes
-
-
-═══ CLUSTERS WORKFLOW ═══
-1. Auto-cluster AI creates/updates clusters
- └─> Clusters created with status='new'
-
-2. AI generate-ideas runs on 'new' clusters
- └─> Ideas created for cluster
- └─> Clusters status changes to 'mapped'
-
-3. [Optional] User manually disables cluster
- └─> Clusters.disabled = true
- └─> Excluded from all processes
-
-
-═══ IDEAS WORKFLOW ═══
-1. AI generate-ideas creates ideas for clusters
- └─> Ideas created with status='new'
-
-2. User bulk-queues ideas to writer
- └─> Task created in Writer module
- └─> Ideas status changes to 'queued'
-
-3. Writer AI (generate-content) creates content
- └─> Content record created
- └─> Task.status = 'completed'
- └─> Ideas.status = 'completed' [Auto-sync from Task]
-
-4. [Optional] User manually disables idea
- └─> Ideas.disabled = true
- └─> Excluded from all processes
-```
-
----
-
-## 🔧 Implementation Changes
-
-### Backend Model Changes
-
-#### 1. `/backend/igny8_core/business/planning/models.py`
-
-**Keywords Model:**
-```python
-# REMOVE old STATUS_CHOICES
-# OLD:
-STATUS_CHOICES = [
- ('active', 'Active'),
- ('pending', 'Pending'),
- ('archived', 'Archived'),
-]
-
-# NEW:
-STATUS_CHOICES = [
- ('new', 'New'),
- ('mapped', 'Mapped'),
-]
-status = models.CharField(
- max_length=50,
- choices=STATUS_CHOICES,
- default='new'
-)
-
-# ADD new filter field:
-disabled = models.BooleanField(default=False, help_text="Exclude from processes")
-```
-
-**Clusters Model:**
-```python
-# ADD STATUS_CHOICES (currently hardcoded as default='active', no choices)
-# CURRENT: status = models.CharField(max_length=50, default='active')
-
-# NEW:
-STATUS_CHOICES = [
- ('new', 'New'),
- ('mapped', 'Mapped'),
-]
-status = models.CharField(
- max_length=50,
- choices=STATUS_CHOICES,
- default='new'
-)
-
-# ADD new filter field:
-disabled = models.BooleanField(default=False, help_text="Exclude from processes")
-```
-
-**ContentIdeas Model:**
-```python
-# UPDATE STATUS_CHOICES
-# REMOVE 'scheduled', 'published'
-STATUS_CHOICES = [
- ('new', 'New'),
- ('queued', 'Queued'),
- ('completed', 'Completed'),
-]
-status = models.CharField(
- max_length=50,
- choices=STATUS_CHOICES,
- default='new'
-)
-
-# ADD new filter field:
-disabled = models.BooleanField(default=False, help_text="Exclude from processes")
-```
-
----
-
-### Backend AI Function Updates
-
-#### 2. `/backend/igny8_core/ai/functions/auto_cluster.py`
-
-**Location: Line ~297 in save_output()**
-```python
-# CURRENT:
-status='active'
-
-# NEW:
-status='mapped' # When keywords are assigned to cluster
-```
-
----
-
-#### 3. `/backend/igny8_core/ai/functions/generate_ideas.py`
-
-**Location: After ideas created in save_output()**
-```python
-# NEW: Add after creating ideas
-# Update cluster status from 'new' to 'mapped' after ideas generated
-for cluster in clusters_used:
- if cluster.status == 'new':
- cluster.status = 'mapped'
- cluster.save()
-```
-
----
-
-#### 4. `/backend/igny8_core/ai/functions/generate_content.py`
-
-**Location: Line ~318 in save_output()**
-```python
-# CURRENT:
-task.status = 'completed'
-task.save()
-
-# NEW: Auto-sync idea status from task
-task.status = 'completed'
-task.save()
-
-# NEW: Update related idea to 'completed'
-if hasattr(task, 'idea') and task.idea:
- idea = task.idea
- idea.status = 'completed'
- idea.save()
-```
-
----
-
-### Backend API Updates
-
-#### 5. `/backend/igny8_core/modules/planner/views.py`
-
-**Queue ideas to writer (Line ~1084):**
-```python
-# CURRENT:
-idea.status = 'scheduled'
-
-# NEW:
-idea.status = 'queued'
-```
-
-**CSV import defaults (Line ~563):**
-```python
-# CURRENT:
-status=row.get('status', 'pending') or 'pending'
-
-# NEW:
-status=row.get('status', 'new') or 'new'
-```
-
-**Filter out disabled items in list views:**
-```python
-# NEW: When returning lists, exclude disabled=true (optional, configurable)
-queryset = queryset.filter(disabled=False) # Or show both with filter option
-```
-
----
-
-### Frontend Configuration Updates
-
-#### 6. `/frontend/src/config/pages/keywords.config.tsx`
-
-**Table Column - Status Badge (Lines ~230-248):**
-```typescript
-// CURRENT:
-new: 'amber', active: 'green', archived: 'red'
-
-// NEW:
-new: 'amber', mapped: 'green'
-
-// ADD: Display 'disabled' badge if disabled=true
-```
-
-**Filter Dropdown (Lines ~310-318):**
-```typescript
-// CURRENT:
-options: ['pending', 'active', 'archived']
-
-// NEW:
-options: ['new', 'mapped'],
-additionalFilters: [
- { key: 'disabled', label: 'Show Disabled', type: 'checkbox', default: false }
-]
-```
-
-**Form Field Default (Lines ~560-570):**
-```typescript
-// CURRENT:
-default: 'pending'
-
-// NEW:
-default: 'new'
-
-// ADD: disabled checkbox in form
-```
-
----
-
-#### 7. `/frontend/src/config/pages/clusters.config.tsx`
-
-**Table Column - Status Badge (Lines ~190-200):**
-```typescript
-// CURRENT:
-(missing or wrong values)
-
-// NEW:
-new: 'amber', mapped: 'green'
-
-// ADD: Display 'disabled' badge if disabled=true
-```
-
-**Filter Dropdown (Lines ~240-253):**
-```typescript
-// CURRENT:
-options: ['new', 'idea', 'mapped']
-
-// NEW:
-options: ['new', 'mapped'],
-additionalFilters: [
- { key: 'disabled', label: 'Show Disabled', type: 'checkbox', default: false }
-]
-```
-
-**Form Field (Lines ~405-418):**
-```typescript
-// ADD: disabled checkbox in form
-// Keep status default as 'new'
-```
-
----
-
-#### 8. `/frontend/src/config/pages/ideas.config.tsx`
-
-**Table Column - Status Badge (Lines ~170-185):**
-```typescript
-// CURRENT:
-new: 'amber', scheduled: 'blue', completed: 'blue', published: 'green'
-
-// NEW:
-new: 'amber', queued: 'blue', completed: 'green'
-
-// ADD: Display 'disabled' badge if disabled=true
-```
-
-**Filter Dropdown (Lines ~218-228):**
-```typescript
-// CURRENT:
-options: ['new', 'scheduled', 'completed', 'published']
-
-// NEW:
-options: ['new', 'queued', 'completed'],
-additionalFilters: [
- { key: 'disabled', label: 'Show Disabled', type: 'checkbox', default: false }
-]
-```
-
-**Form Field (Lines ~372-385):**
-```typescript
-// REMOVE: 'published' option
-// ADD: disabled checkbox in form
-// Keep status default as 'new'
-```
-
----
-
-### Frontend Dashboard
-
-#### 9. `/frontend/src/pages/Planner/Dashboard.tsx`
-
-**Status Metrics:**
-```typescript
-// Update calculations:
-// - Keywords: new vs mapped
-// - Clusters: new vs mapped
-// - Ideas: new vs queued vs completed
-
-// Optional: Add disabled count metrics
-```
-
----
-
-## 📍 Change Summary
-
-### Total Files: 9
-
-| File | Changes | Type |
-|------|---------|------|
-| **models.py** | Add STATUS_CHOICES for Clusters; Update Keywords/Ideas; Add `disabled` field to all 3 | Backend |
-| **auto_cluster.py** | Line 297: `status='active'` → `status='mapped'` | Backend AI |
-| **generate_ideas.py** | After ideas created: Set cluster `status='mapped'` | Backend AI |
-| **generate_content.py** | Line 318: Also sync `idea.status='completed'` from task | Backend AI |
-| **views.py** | Queue ideas (line 1084): `'scheduled'` → `'queued'`; CSV import: `'pending'` → `'new'` | Backend API |
-| **keywords.config.tsx** | Update badge/filter/form for new/mapped; Add disabled checkbox | Frontend Config |
-| **clusters.config.tsx** | Update badge/filter/form for new/mapped; Add disabled checkbox | Frontend Config |
-| **ideas.config.tsx** | Update badge/filter/form for new/queued/completed; Add disabled checkbox | Frontend Config |
-| **Dashboard.tsx** | Update metrics calculations for new status values | Frontend Page |
-
----
-
-## ✅ Workflow Validations
-
-### Keywords
-```
-✓ new → mapped (via auto_cluster)
-✓ Can toggle disabled at any time (no workflow impact)
-✓ Disabled items excluded from auto-cluster suggestions
-```
-
-### Clusters
-```
-✓ new → mapped (via generate_ideas)
-✓ Can toggle disabled at any time (no workflow impact)
-✓ Disabled items excluded from idea generation
-```
-
-### Ideas
-```
-✓ new → queued (via bulk_queue_to_writer)
-✓ queued → completed (via generate_content, tracked via Task.status)
-✓ Can toggle disabled at any time (no workflow impact)
-✓ Disabled items excluded from queue suggestions
-```
-
----
-
-## 🗑️ Data Migration Strategy
-
-### Django Migration File
-**File:** `backend/igny8_core/business/planning/migrations/NNNN_unified_status_fields.py`
-
-```python
-# Forward migration:
-# 1. Add disabled=BooleanField(default=False) to all 3 models
-# 2. Add STATUS_CHOICES to Clusters model
-# 3. Update Keywords.status data:
-# - pending → new
-# - active → mapped
-# - archived → mapped + set disabled=True
-# 4. Update Clusters.status data:
-# - active (with ideas_count > 0) → mapped
-# - active (with ideas_count = 0) → new
-# 5. Update ContentIdeas.status data:
-# - scheduled → queued
-# - published → completed
-# - new → new (no change)
-
-# Reverse migration:
-# 1. Remove disabled field from all 3 models
-# 2. Restore old STATUS_CHOICES
-# 3. Reverse data transformations:
-# - Keywords: new→pending, mapped→active, disabled=True→archived
-# - Clusters: Remove STATUS_CHOICES, set all to 'active'
-# - Ideas: queued→scheduled, completed→published
-```
-
----
-
-## 🧪 Testing Checklist
-
-- [ ] Keywords: status='new' by default
-- [ ] Keywords: auto_cluster sets status='mapped'
-- [ ] Clusters: status='new' by default
-- [ ] Clusters: generate_ideas sets status='mapped'
-- [ ] Ideas: status='new' by default
-- [ ] Ideas: bulk_queue_to_writer sets status='queued'
-- [ ] Ideas: generate_content sets status='completed' (via task sync)
-- [ ] All modules: disabled=true excludes from processes
-- [ ] All modules: disabled checkbox toggles correctly
-- [ ] Dashboard: metrics use new status values
-- [ ] Filters: disabled checkbox hides disabled items by default
-- [ ] Migration: old data transforms correctly
-
----
-
-## 🎯 Key Differences from Previous Plan
-
-| Previous | Now Corrected |
-|----------|---------------|
-| `disabled` was workflow step | `disabled` is filter status only |
-| 3 workflows statuses per module | 2 workflow statuses per module |
-| Published status for Ideas | Completed is final; publish is separate action |
-| Ideas tracked separately | Ideas auto-sync from Task status |
-| Unclear disabled behavior | Clear: disabled excluded from all processes |
-
----
-
-**Status:** ✅ Plan Complete & Corrected
-**Ready for:** Implementation Phase 1 (Backend Models)
-
diff --git a/STATUS-UNIFIED-STRUCTURE-PLAN.md b/STATUS-UNIFIED-STRUCTURE-PLAN.md
deleted file mode 100644
index 9a1572c1..00000000
--- a/STATUS-UNIFIED-STRUCTURE-PLAN.md
+++ /dev/null
@@ -1,526 +0,0 @@
-# Unified Status Structure Plan - Keywords, Clusters, Ideas
-
-**Date:** December 3, 2025
-**Objective:** Implement unified, workflow-driven status values across all three modules
-
----
-
-## 🎯 Proposed Unified Status Structure
-
-### Module-Specific Status Values
-
-#### KEYWORDS Module
-**Current:** `pending`, `active`, `archived`
-**Proposed:** `new`, `mapped`, `disabled`
-
-| Status | Meaning | When Used | Next Step |
-|--------|---------|-----------|-----------|
-| **new** | Keyword just attached to site, not yet assigned to cluster | User adds keyword | AI auto-cluster runs → `mapped` |
-| **mapped** | Keyword is assigned to a cluster | AI clustering completes OR manual assignment | Can generate ideas from cluster |
-| **disabled** | Keyword is archived/inactive | User manually disables | No workflow activity |
-
-**Workflow:**
-```
-new → mapped → (can be used for ideas)
- ↓
-disabled (any time)
-```
-
----
-
-#### CLUSTERS Module
-**Current:** `active`, `pending`, `archived`
-**Proposed:** `new`, `mapped`, `disabled`
-
-| Status | Meaning | When Used | Next Step |
-|--------|---------|-----------|-----------|
-| **new** | Cluster created but no content ideas generated yet | AI clustering creates cluster OR manual creation | AI generate_ideas runs → `mapped` |
-| **mapped** | Cluster has ideas generated from it | AI generate_ideas completes | Ideas ready to queue to writer |
-| **disabled** | Cluster is archived/inactive | User manually disables | No workflow activity |
-
-**Workflow:**
-```
-new → mapped → (ideas queue to writer)
- ↓
-disabled (any time)
-```
-
----
-
-#### IDEAS Module
-**Current:** `new`, `scheduled`, `completed`, `published`
-**Proposed:** `new`, `queued`, `completed`, `published`
-
-| Status | Meaning | When Used | Next Step |
-|--------|---------|-----------|-----------|
-| **new** | Idea generated by AI but not queued to writer yet | AI generate_ideas creates idea | User queues to writer → `queued` |
-| **queued** | Idea queued to writer, task created in Writer module | Bulk queue to writer API called | Content generated by writer → `completed` |
-| **completed** | Content generated from idea (Task completed with content) | generate_content AI function creates Content record | Manual publish → `published` |
-| **published** | Content published to site | User publishes OR auto-publish | Final state |
-
-**Workflow:**
-```
-new → queued → completed → published
-```
-
----
-
-## 📊 Status Update Flow Diagram
-
-```
-KEYWORDS WORKFLOW:
-1. User adds SeedKeyword → Keywords status='new'
-2. AI auto_cluster runs → Keywords status='mapped' (assigned to cluster)
-3. User can disable → Keywords status='disabled'
-
-CLUSTERS WORKFLOW:
-1. AI creates cluster → Clusters status='new'
-2. AI generate_ideas runs → Clusters status='mapped' (has ideas)
-3. User can disable → Clusters status='disabled'
-
-IDEAS WORKFLOW:
-1. AI creates idea → Ideas status='new'
-2. User bulk queues ideas → Ideas status='queued' (task created in Writer)
-3. Writer AI generates content → Ideas status='completed' (Content record created)
-4. User publishes content → Ideas status='published'
-```
-
----
-
-## 🔧 Change Locations & Impact
-
-### Backend Model Files to Update
-
-#### 1. `/backend/igny8_core/business/planning/models.py`
-
-**Keywords Model (Lines 42-46):**
-```python
-# CURRENT:
-STATUS_CHOICES = [
- ('active', 'Active'),
- ('pending', 'Pending'),
- ('archived', 'Archived'),
-]
-
-# PROPOSED:
-STATUS_CHOICES = [
- ('new', 'New'),
- ('mapped', 'Mapped'),
- ('disabled', 'Disabled'),
-]
-
-# DEFAULT: Change from 'pending' → 'new'
-```
-
-**Clusters Model (Line 12):**
-```python
-# CURRENT:
-status = models.CharField(max_length=50, default='active')
-
-# PROPOSED:
-status = models.CharField(max_length=50, default='new',
- choices=[('new', 'New'), ('mapped', 'Mapped'), ('disabled', 'Disabled')])
-```
-
-**ContentIdeas Model (Lines 150-157):**
-```python
-# CURRENT:
-STATUS_CHOICES = [
- ('new', 'New'),
- ('scheduled', 'Scheduled'),
- ('published', 'Published'),
-]
-
-# PROPOSED:
-STATUS_CHOICES = [
- ('new', 'New'),
- ('queued', 'Queued'),
- ('completed', 'Completed'),
- ('published', 'Published'),
-]
-
-# DEFAULT: Keep 'new'
-```
-
----
-
-### Backend AI Function Files to Update
-
-#### 2. `/backend/igny8_core/ai/functions/auto_cluster.py` (Line 297)
-
-**When keywords are assigned to clusters:**
-```python
-# CURRENT:
-status='active'
-
-# PROPOSED:
-status='mapped'
-```
-
-**Location:** In `save_output()` method when updating Keywords
-
----
-
-#### 3. `/backend/igny8_core/ai/functions/generate_ideas.py` (Line 224)
-
-**When clusters change status after ideas generated:**
-```python
-# CURRENT: No cluster status update
-
-# PROPOSED: After creating ideas, update cluster status:
-# In save_output() method, after creating ideas:
-cluster.status = 'mapped'
-cluster.save()
-```
-
-**Additional:** Ideas default stays `status='new'`
-
----
-
-#### 4. `/backend/igny8_core/ai/functions/generate_content.py` (Line 318)
-
-**When content is generated from a task:**
-```python
-# CURRENT:
-task.status = 'completed'
-task.save()
-
-# PROPOSED: Also update the related Idea status:
-task.status = 'completed'
-task.save()
-
-# NEW: Update idea to completed
-if hasattr(task, 'idea') and task.idea:
- idea = task.idea
- idea.status = 'completed'
- idea.save()
-```
-
-**Location:** In `save_output()` method after content is created
-
----
-
-### Backend API Endpoint Files to Update
-
-#### 5. `/backend/igny8_core/modules/planner/views.py`
-
-**Line 1029 - Queue ideas to writer filter:**
-```python
-# CURRENT:
-queueable_ideas = all_ideas.filter(status='new')
-
-# NO CHANGE NEEDED (stays 'new')
-```
-
-**Line 1084 - Update idea status when queued:**
-```python
-# CURRENT:
-idea.status = 'scheduled'
-idea.save()
-
-# PROPOSED:
-idea.status = 'queued'
-idea.save()
-```
-
-**Line 563 - Bulk create keywords from CSV:**
-```python
-# CURRENT:
-status=row.get('status', 'pending') or 'pending'
-
-# PROPOSED:
-status=row.get('status', 'new') or 'new'
-```
-
----
-
-### Frontend Configuration Files to Update
-
-#### 6. `/frontend/src/config/pages/keywords.config.tsx`
-
-**Table Column Status Badge (Lines 230-248):**
-```typescript
-// CURRENT:
-pending: 'amber', active: 'green', archived: 'red'
-
-// PROPOSED:
-new: 'amber', mapped: 'green', disabled: 'red'
-```
-
-**Filter Dropdown (Lines 310-318):**
-```typescript
-// CURRENT:
-options: ['pending', 'active', 'archived']
-
-// PROPOSED:
-options: ['new', 'mapped', 'disabled']
-```
-
-**Form Field Default (Lines 560-570):**
-```typescript
-// CURRENT:
-default: 'pending'
-
-// PROPOSED:
-default: 'new'
-```
-
----
-
-#### 7. `/frontend/src/config/pages/clusters.config.tsx`
-
-**Table Column Status Badge (Lines 190-200):**
-```typescript
-// CURRENT:
-active: 'green', archived: 'red' (inconsistent from backend)
-
-// PROPOSED:
-new: 'amber', mapped: 'green', disabled: 'red'
-```
-
-**Filter Dropdown (Lines 240-253):**
-```typescript
-// CURRENT:
-options: ['active', 'archived'] (missing 'new')
-
-// PROPOSED:
-options: ['new', 'mapped', 'disabled']
-```
-
-**Form Field Default (Lines 405-418):**
-```typescript
-// CURRENT:
-default: 'new'
-
-// PROPOSED:
-default: 'new' (no change, already correct)
-```
-
----
-
-#### 8. `/frontend/src/config/pages/ideas.config.tsx`
-
-**Table Column Status Badge (Lines 170-185):**
-```typescript
-// CURRENT:
-new: 'amber', scheduled: 'blue', completed: 'blue', published: 'green'
-
-// PROPOSED:
-new: 'amber', queued: 'blue', completed: 'blue', published: 'green'
-```
-
-**Filter Dropdown (Lines 218-228):**
-```typescript
-// CURRENT:
-options: ['new', 'scheduled', 'completed', 'published']
-// NOTE: missing 'completed' in some places
-
-// PROPOSED:
-options: ['new', 'queued', 'completed', 'published']
-```
-
-**Form Field Default (Lines 372-385):**
-```typescript
-// CURRENT:
-default: 'new'
-
-// PROPOSED:
-default: 'new' (no change)
-```
-
----
-
-### Frontend Dashboard & State Files
-
-#### 9. `/frontend/src/pages/Planner/Dashboard.tsx`
-
-**Status Metrics (Lines 121-155):**
-```typescript
-// Updates status counting logic
-// From: keywordsByStatus, clustersByStatus, ideaByStatus
-// To: Use new status values
-
-// Example refactor:
-// OLD: keywordsByStatus['active'] vs keywordsByStatus['pending']
-// NEW: keywordsByStatus['mapped'] vs keywordsByStatus['new']
-```
-
-**No API call changes needed** - API returns correct values
-
----
-
-#### 10. `/frontend/src/services/api.ts`
-
-**No changes needed** - Only returns what backend provides
-
----
-
-### Frontend Component Files
-
-#### 11. `/frontend/src/pages/Planner/Keywords.tsx`
-
-**Status Filter Logic (if hardcoded):**
-- Search for status comparisons
-- Update from old values → new values
-
-#### 12. `/frontend/src/pages/Planner/Clusters.tsx`
-
-**Status Filter Logic (if hardcoded):**
-- Search for status comparisons
-- Update from old values → new values
-
-#### 13. `/frontend/src/pages/Planner/Ideas.tsx`
-
-**Status Filter Logic (if hardcoded):**
-- Update from `scheduled` → `queued`
-- Keep `new`, `completed`, `published`
-
----
-
-### Database Migration Files
-
-#### 14. New Django Migration Required
-
-**File to create:** `/backend/igny8_core/business/planning/migrations/NNNN_update_status_choices.py`
-
-```python
-# Migration tasks:
-# 1. Update Keywords STATUS_CHOICES in model
-# 2. Data migration: pending → new, active → mapped, archived → disabled
-# 3. Update Clusters status field with choices
-# 4. Data migration: active → new (or map by count of ideas)
-# 5. Update ContentIdeas STATUS_CHOICES
-# 6. Data migration: scheduled → queued
-```
-
-**Changes needed:**
-- Keywords: pending→new, active→mapped, archived→disabled
-- Clusters: active→new or mapped (based on ideas_count), archived→disabled
-- ContentIdeas: scheduled→queued
-
----
-
-## 📍 Location Summary
-
-### Total Files to Update: 13
-
-| Category | Count | Files |
-|----------|-------|-------|
-| Backend Models | 1 | models.py |
-| Backend AI Functions | 3 | auto_cluster.py, generate_ideas.py, generate_content.py |
-| Backend API Views | 1 | views.py |
-| Frontend Configs | 3 | keywords.config.tsx, clusters.config.tsx, ideas.config.tsx |
-| Frontend Pages | 3 | Dashboard.tsx, Keywords.tsx, Clusters.tsx, Ideas.tsx |
-| Database Migrations | 1 | New migration file |
-| **TOTAL** | **13** | |
-
----
-
-## 🔄 Dependency Order
-
-### Phase 1: Backend Models & Data Migration (BLOCKER)
-1. Update `models.py` STATUS_CHOICES for all 3 models
-2. Create Django migration with data transformation
-3. Run migration on database
-4. Test: Backend API returns new status values
-
-### Phase 2: AI Functions (Status Update Logic)
-5. Update `auto_cluster.py` line 297: keywords status → 'mapped'
-6. Add to `generate_ideas.py`: clusters status → 'mapped' after ideas created
-7. Update `generate_content.py` line 318: ideas status → 'completed' after content created
-8. Test: AI workflows set correct status values
-
-### Phase 3: Backend API (Response Values)
-9. Update `views.py` line 563: CSV import defaults to 'new'
-10. Update `views.py` line 1084: queue to writer uses 'queued'
-11. Test: API responses have new status values
-
-### Phase 4: Frontend Configuration (Display Logic)
-12. Update `keywords.config.tsx` (3 locations: badge, filter, form)
-13. Update `clusters.config.tsx` (3 locations: badge, filter, form)
-14. Update `ideas.config.tsx` (3 locations: badge, filter, form)
-15. Test: Filters and forms display new status values
-
-### Phase 5: Frontend Pages (State Management)
-16. Update `Dashboard.tsx` status metrics calculations
-17. Update `Keywords.tsx` status filters (if hardcoded)
-18. Update `Clusters.tsx` status filters (if hardcoded)
-19. Update `Ideas.tsx` status filters and comparisons
-20. Test: Dashboard shows correct counts, filters work
-
----
-
-## 🧪 Testing Checklist
-
-### Backend Tests
-- [ ] Models accept new status values only (no old values allowed)
-- [ ] Migration transforms data correctly
-- [ ] Auto-cluster: Keywords change from new → mapped
-- [ ] Generate ideas: Clusters change from new → mapped
-- [ ] Generate content: Ideas change from queued → completed
-- [ ] API returns new status values
-
-### Frontend Tests
-- [ ] Keywords: Table shows new/mapped/disabled badges with correct colors
-- [ ] Keywords: Filter dropdown shows new/mapped/disabled options
-- [ ] Keywords: Create form defaults to 'new'
-- [ ] Clusters: Table shows new/mapped/disabled badges
-- [ ] Clusters: Filter shows new/mapped/disabled options
-- [ ] Clusters: Create form defaults to 'new'
-- [ ] Ideas: Table shows new/queued/completed/published badges
-- [ ] Ideas: Filter shows all 4 status options
-- [ ] Ideas: Queue to writer changes status to 'queued'
-- [ ] Dashboard: Metrics count correctly with new status values
-- [ ] Dashboard: Workflow percentage bars calculate correctly
-
-### Integration Tests
-- [ ] Full workflow: keyword → cluster → idea → queued → completed → published
-- [ ] Status transitions are unidirectional (new→mapped, queued→completed, etc.)
-- [ ] Disabled items don't appear in workflow suggestions
-- [ ] Bulk operations update status correctly
-
----
-
-## 🎯 Benefits of Unified Structure
-
-1. **Consistency:** All modules follow same pattern (new → mapped → disabled)
-2. **Clarity:** Status names reflect actual workflow state, not just data state
-3. **Scalability:** Easy to add new statuses without confusion
-4. **Maintainability:** Single place to understand entire status flow
-5. **User Understanding:** Users immediately understand workflow progression
-6. **AI Integration:** AI functions have clear status update points
-
----
-
-## ⚠️ Breaking Changes Alert
-
-### For API Consumers
-- Old status values `pending`, `active`, `archived`, `scheduled` will no longer be accepted
-- API will return only `new`, `mapped`, `disabled`, `queued`, `completed`, `published`
-- Clients must update filtering logic
-
-### For Database
-- Existing records will be migrated with data transformation
-- No data loss, but status values will change
-- Recommended: Backup database before running migration
-
-### For Frontend
-- Old hardcoded status comparisons must be updated
-- Filter options in dropdowns must match new values
-- Status badges must use new color mappings
-
----
-
-## 📋 Rollback Plan
-
-If issues arise:
-1. Reverse Django migration (restores old status values and data)
-2. Revert backend code to previous version
-3. Revert frontend configs to previous version
-4. Test API and UI return to old behavior
-
----
-
-**Status:** Plan Complete - Ready for Implementation
-**Next Step:** Execute Phase 1 (Backend Models & Migration)
-
diff --git a/KEYWORDS-CLUSTERS-IDEAS-COMPLETE-MAPPING.md b/docs/KEYWORDS-CLUSTERS-IDEAS-COMPLETE-MAPPING.md
similarity index 100%
rename from KEYWORDS-CLUSTERS-IDEAS-COMPLETE-MAPPING.md
rename to docs/KEYWORDS-CLUSTERS-IDEAS-COMPLETE-MAPPING.md
diff --git a/docs/SITEBUILDER-REMOVAL-MIGRATION-GUIDE.md b/docs/SITEBUILDER-REMOVAL-MIGRATION-GUIDE.md
deleted file mode 100644
index 958e9384..00000000
--- a/docs/SITEBUILDER-REMOVAL-MIGRATION-GUIDE.md
+++ /dev/null
@@ -1,351 +0,0 @@
-# SiteBuilder Removal - Complete Migration Guide
-
-**Date:** December 1, 2025
-**Status:** Code changes completed, database migration pending
-
----
-
-## Summary
-
-All SiteBuilder and Blueprint functionality has been removed from the IGNY8 system. The taxonomy system has been simplified to use the direct `Content.taxonomy_terms` many-to-many relationship with the `ContentTaxonomy` model.
-
----
-
-## What Was Removed
-
-### Backend Models (Django)
-- ✅ `SiteBlueprint` - Site structure blueprints
-- ✅ `PageBlueprint` - Individual page definitions
-- ✅ `SiteBlueprintCluster` - Cluster to blueprint mappings
-- ✅ `SiteBlueprintTaxonomy` - Blueprint taxonomy definitions
-- ✅ `BusinessType`, `AudienceProfile`, `BrandPersonality`, `HeroImageryDirection` - SiteBuilder metadata options
-- ✅ `ContentTaxonomyMap` - Replaced by `Content.taxonomy_terms` M2M field
-
-### Backend Modules
-- ✅ Removed entire `igny8_core.modules.site_builder` module
-- ✅ Removed from `INSTALLED_APPS` in settings.py
-- ✅ Removed `/api/v1/site-builder/` URL patterns
-- ✅ Cleaned up `site_building/models.py`, `site_building/admin.py`
-
-### Backend Services & Views
-- ✅ Updated `PublisherService` - removed `publish_to_sites()` method
-- ✅ Updated `PublisherViewSet` - removed blueprint publishing actions
-- ✅ Updated `DeploymentRecordViewSet` - removed blueprint references
-- ✅ Updated `PublishingRecord` model - removed `site_blueprint` field
-- ✅ Updated `DeploymentRecord` model - removed `site_blueprint` field
-- ✅ Fixed `metadata_mapping_service.py` - removed ContentTaxonomyMap
-- ✅ Fixed `candidate_engine.py` - uses `Content.taxonomy_terms` now
-- ✅ Fixed `sites_renderer_adapter.py` - uses M2M taxonomy relationship
-- ✅ Fixed `planner/serializers.py` - removed SiteBlueprintTaxonomy import
-
-### Frontend
-- ✅ Removed `frontend/src/modules/siteBuilder/` directory
-- ✅ Removed `frontend/src/types/siteBuilder.ts`
-- ✅ Removed `frontend/src/services/siteBuilder.api.ts`
-- ✅ Removed SiteBlueprint API functions from `services/api.ts`
-- ✅ Removed SiteBuilder routes from navigation
-
----
-
-## Current Taxonomy System
-
-### Simplified Architecture
-
-**Before (Complex - SiteBuilder era):**
-```
-Content → ContentTaxonomyMap → SiteBlueprintTaxonomy → Clusters
- (through table) (blueprint planning)
-```
-
-**After (Simplified - Current):**
-```
-Content ←→ ContentTaxonomy (many-to-many direct relationship)
- ↓
- Cluster (foreign key)
-```
-
-### ContentTaxonomy Model
-**Location:** `backend/igny8_core/business/content/models.py`
-
-**Fields:**
-- `name` - Term name (e.g., "Outdoor Living Design")
-- `slug` - URL-safe version
-- `taxonomy_type` - Choices: `category`, `tag`
-- `external_id` - WordPress term_id for sync
-- `external_taxonomy` - WordPress taxonomy slug (category, post_tag)
-- `description` - Term description
-- `account`, `site`, `sector` - Multi-tenancy fields
-
-**Relationship:**
-- `Content.taxonomy_terms` - ManyToManyField to ContentTaxonomy
-- Categories/tags are AI-generated and linked directly to Content
-
----
-
-## How Content Taxonomy Works Now
-
-### Publishing Flow (IGNY8 → WordPress)
-
-```python
-# In wordpress_publishing.py task
-
-# STEP 4: Get categories from Content.taxonomy_terms
-categories = [
- term.name
- for term in content.taxonomy_terms.filter(taxonomy_type='category')
-]
-
-# Fallback to cluster if no taxonomy_terms
-if not categories and content.cluster:
- categories.append(content.cluster.name)
-
-# STEP 5: Get tags from taxonomy_terms + keywords
-tags = [
- term.name
- for term in content.taxonomy_terms.filter(taxonomy_type='tag')
-]
-
-# Add keywords as tags
-if content.primary_keyword not in tags:
- tags.append(content.primary_keyword)
-for keyword in content.secondary_keywords:
- if keyword not in tags:
- tags.append(keyword)
-```
-
-### Data Flow
-
-```
-Keywords → Clusters → Ideas → Tasks → Content
- ├── taxonomy_terms (M2M)
- │ ├── Categories
- │ └── Tags
- ├── cluster (FK)
- ├── primary_keyword
- └── secondary_keywords
- ↓
- WordPress Publish
- ├── Categories (from taxonomy_terms + cluster)
- └── Tags (from taxonomy_terms + keywords)
-```
-
----
-
-## Django Admin
-
-**ContentTaxonomy is registered** in `backend/igny8_core/modules/writer/admin.py`:
-- View at: `/admin/writer/contenttaxonomy/`
-- Shows: name, taxonomy_type, slug, external_id, external_taxonomy, site, sector
-- Searchable by: name, slug, external_taxonomy
-- Filterable by: taxonomy_type, site, sector
-
----
-
-## Database Migration (PENDING)
-
-**Migration File:** `backend/igny8_core/business/site_building/migrations/0002_remove_blueprint_models.py`
-
-**Status:** Created but not applied (requires external PostgreSQL access)
-
-### Manual SQL Commands
-
-Run these SQL commands directly on your production PostgreSQL database:
-
-```sql
--- Drop foreign key constraints first
-ALTER TABLE igny8_publishing_records
- DROP CONSTRAINT IF EXISTS igny8_publishing_recor_site_blueprint_id_9f4e8c7a_fk_igny8_sit CASCADE;
-
-ALTER TABLE igny8_deployment_records
- DROP CONSTRAINT IF EXISTS igny8_deployment_recor_site_blueprint_id_3a2b7c1d_fk_igny8_sit CASCADE;
-
--- Drop blueprint tables
-DROP TABLE IF EXISTS igny8_site_blueprint_taxonomies CASCADE;
-DROP TABLE IF EXISTS igny8_site_blueprint_clusters CASCADE;
-DROP TABLE IF EXISTS igny8_page_blueprints CASCADE;
-DROP TABLE IF EXISTS igny8_site_blueprints CASCADE;
-
--- Drop SiteBuilder metadata tables
-DROP TABLE IF EXISTS igny8_site_builder_business_types CASCADE;
-DROP TABLE IF EXISTS igny8_site_builder_audience_profiles CASCADE;
-DROP TABLE IF EXISTS igny8_site_builder_brand_personalities CASCADE;
-DROP TABLE IF EXISTS igny8_site_builder_hero_imagery CASCADE;
-
--- Drop site_blueprint_id columns
-ALTER TABLE igny8_publishing_records DROP COLUMN IF EXISTS site_blueprint_id CASCADE;
-ALTER TABLE igny8_deployment_records DROP COLUMN IF EXISTS site_blueprint_id CASCADE;
-
--- Drop indexes
-DROP INDEX IF EXISTS igny8_publishing_recor_site_blueprint_id_des_b7c4e5f8_idx;
-
--- Mark migration as applied
-INSERT INTO django_migrations (app, name, applied)
-VALUES ('site_building', '0002_remove_blueprint_models', NOW())
-ON CONFLICT DO NOTHING;
-```
-
----
-
-## Files Modified
-
-### Backend Python Files (24 files)
-1. `backend/igny8_core/business/site_building/models.py` - All models removed
-2. `backend/igny8_core/business/site_building/admin.py` - All admin classes removed
-3. `backend/igny8_core/business/publishing/models.py` - Removed site_blueprint FK
-4. `backend/igny8_core/business/publishing/services/publisher_service.py` - Removed publish_to_sites
-5. `backend/igny8_core/business/publishing/services/adapters/sites_renderer_adapter.py` - Updated taxonomy usage
-6. `backend/igny8_core/business/content/services/metadata_mapping_service.py` - Removed ContentTaxonomyMap
-7. `backend/igny8_core/business/linking/services/candidate_engine.py` - Updated to M2M taxonomy
-8. `backend/igny8_core/business/optimization/services/analyzer.py` - Updated taxonomy check
-9. `backend/igny8_core/modules/publisher/views.py` - Removed blueprint actions
-10. `backend/igny8_core/modules/planner/serializers.py` - Removed SiteBlueprintTaxonomy
-11. `backend/igny8_core/tasks/wordpress_publishing.py` - Uses Content.taxonomy_terms
-12. `backend/igny8_core/urls.py` - Removed site-builder URL
-13. `backend/igny8_core/settings.py` - Removed site_builder from INSTALLED_APPS
-
-### Frontend TypeScript Files (3 files)
-1. `frontend/src/services/api.ts` - Removed SiteBlueprint API functions
-2. Removed: `frontend/src/types/siteBuilder.ts`
-3. Removed: `frontend/src/services/siteBuilder.api.ts`
-4. Removed: `frontend/src/modules/siteBuilder/` directory
-
-### Migrations
-1. Created: `backend/igny8_core/business/site_building/migrations/0002_remove_blueprint_models.py`
-
----
-
-## Testing Checklist
-
-### Backend Health Check
-```bash
-# Check if backend starts successfully
-docker compose -f docker-compose.app.yml logs igny8_backend | grep -i "error\|exception"
-
-# Should show no import errors
-```
-
-### Taxonomy Workflow Test
-
-1. **Check ContentTaxonomy in Admin**
- - Go to `/admin/writer/contenttaxonomy/`
- - Verify model is accessible
- - Check existing taxonomy terms
-
-2. **Test Content Creation**
- ```bash
- # In Django shell
- from igny8_core.business.content.models import Content, ContentTaxonomy
-
- content = Content.objects.first()
- print(f"Taxonomy terms: {content.taxonomy_terms.count()}")
- print(f"Cluster: {content.cluster.name if content.cluster else 'None'}")
- ```
-
-3. **Test Publishing to WordPress**
- - Create/select content with taxonomy_terms
- - Publish to WordPress from Review page
- - Verify categories and tags appear in WordPress
- - Check logs: `tail -f backend/logs/publish-sync-logs/publish-sync.log`
-
-### Expected Log Output
-```
-[2025-12-01 02:00:00] [INFO] [5-homeg8.com] STEP 4: Loading taxonomy terms...
-[2025-12-01 02:00:00] [INFO] [5-homeg8.com] Found 1 categories from taxonomy_terms
-[2025-12-01 02:00:00] [INFO] [5-homeg8.com] 📁 Category: 'Outdoor Living Design'
-[2025-12-01 02:00:00] [INFO] [5-homeg8.com] ✅ TOTAL categories: 1
-
-[2025-12-01 02:00:00] [INFO] [5-homeg8.com] STEP 5: Loading tags...
-[2025-12-01 02:00:00] [INFO] [5-homeg8.com] 🏷️ Primary keyword: 'outdoor patio design'
-[2025-12-01 02:00:00] [INFO] [5-homeg8.com] 🏷️ Secondary keywords: ['outdoor living spaces', 'outdoor kitchen design']
-[2025-12-01 02:00:00] [INFO] [5-homeg8.com] ✅ TOTAL tags: 3
-```
-
----
-
-## Remaining Legacy References
-
-These files contain SiteBlueprint references in **migrations only** (historical data, safe to ignore):
-- `backend/igny8_core/business/content/migrations/0002_stage1_refactor_task_content_taxonomy.py`
-- `backend/igny8_core/modules/writer/migrations/0001_initial.py`
-- `backend/igny8_core/modules/planner/migrations/0002_initial.py`
-- `backend/igny8_core/tasks/wordpress_publishing_backup.py` (backup file)
-- `backend/igny8_core/tasks/wordpress_publishing_new.py` (backup file)
-
----
-
-## Benefits of Simplified System
-
-### Before (Complex)
-- 5 models: SiteBlueprint, PageBlueprint, SiteBlueprintCluster, SiteBlueprintTaxonomy, ContentTaxonomyMap
-- 3-level indirection: Content → ContentTaxonomyMap → SiteBlueprintTaxonomy
-- Blueprint planning layer for site building
-- Difficult to understand taxonomy relationships
-
-### After (Simple)
-- 1 model: ContentTaxonomy
-- Direct M2M: Content ↔ ContentTaxonomy
-- AI-generated categories/tags linked directly
-- Clear taxonomy-content relationship in Django Admin
-
-### Performance Improvements
-- Fewer database queries (eliminated ContentTaxonomyMap joins)
-- Simpler ORM queries: `content.taxonomy_terms.filter(taxonomy_type='category')`
-- Easier debugging and maintenance
-
----
-
-## Next Steps
-
-1. **Apply Database Migration**
- - Run SQL commands on production PostgreSQL
- - Mark migration as applied in django_migrations table
-
-2. **Test Publishing Workflow**
- - Publish content from Review page
- - Verify categories/tags in WordPress
- - Check sync logs for any errors
-
-3. **Monitor Logs**
- - Backend: `/data/app/igny8/backend/logs/publish-sync-logs/`
- - WordPress: `/wp-content/plugins/igny8-ai-os/logs/publish-sync-logs/`
-
-4. **Update Documentation**
- - Update SYSTEM-ARCHITECTURE doc to reflect simplified taxonomy
- - Remove SiteBuilder references from workflow docs
-
----
-
-## Rollback Plan (If Needed)
-
-If issues arise, you can restore SiteBuilder functionality by:
-
-1. Restore backup files:
- ```bash
- cd /data/app/igny8/backend/igny8_core/modules
- mv site_builder.backup site_builder
- ```
-
-2. Uncomment in settings.py:
- ```python
- 'igny8_core.modules.site_builder.apps.SiteBuilderConfig',
- ```
-
-3. Restore URL pattern in urls.py:
- ```python
- path('api/v1/site-builder/', include('igny8_core.modules.site_builder.urls')),
- ```
-
-4. Reverse database changes (restore from backup)
-
----
-
-## Contact & Support
-
-If you encounter any issues during migration:
-- Check logs in `backend/logs/` and WordPress plugin `logs/`
-- Review Django admin for ContentTaxonomy model
-- Test publishing workflow step by step
-
-**Migration completed by:** GitHub Copilot
-**Date:** December 1, 2025
-**Version:** IGNY8 v1.0 - SiteBuilder Removal
diff --git a/docs/SITEBUILDER-REMOVAL-SUMMARY.md b/docs/SITEBUILDER-REMOVAL-SUMMARY.md
deleted file mode 100644
index ebb2ea3c..00000000
--- a/docs/SITEBUILDER-REMOVAL-SUMMARY.md
+++ /dev/null
@@ -1,364 +0,0 @@
-# SiteBuilder/Blueprint Removal Summary
-
-**Date:** December 1, 2025
-**Status:** ✅ Complete - Backend Healthy
-
-## Overview
-
-Successfully removed all SiteBuilder and Blueprint functionality from IGNY8 system while maintaining the core planner-writer-publisher workflow and WordPress integration.
-
----
-
-## What Was Removed
-
-### 1. Django Models (backend/igny8_core/business/site_building/models.py)
-- ❌ `SiteBlueprint` - Legacy site planning model
-- ❌ `PageBlueprint` - Legacy page planning model
-- ❌ `SiteBlueprintCluster` - Blueprint-cluster relationship
-- ❌ `SiteBlueprintTaxonomy` - Blueprint-taxonomy relationship
-- ❌ `ContentTaxonomyMap` - Replaced with direct M2M
-
-### 2. Django Module
-- ❌ `backend/igny8_core/business/site_builder/` - Entire module removed from INSTALLED_APPS (settings.py line 60)
-- ⚠️ Directory still exists with tests/services but not loaded by Django
-
-### 3. Frontend Components
-- ❌ `frontend/src/modules/siteBuilder/` - Entire directory removed
-- ❌ `frontend/src/services/api.ts` - SiteBlueprint interfaces and functions removed (replaced with comment)
-
-### 4. API Endpoints (backend/igny8_core/modules/publisher/views.py)
-- ❌ `PublisherViewSet.publish_to_sites()` - Blueprint publishing action
-- ❌ `PublisherViewSet.deployment_readiness()` - Blueprint readiness check
-- ❌ `PublisherViewSet.deploy()` - Blueprint deployment action
-
-### 5. Publishing Service Methods (backend/igny8_core/business/publishing/services/publisher_service.py)
-- ❌ `PublisherService.publish_to_sites()` - Blueprint publishing
-- ❌ `PublisherService.get_deployment_status()` - Blueprint deployment status
-
-### 6. Publishing Models Foreign Keys
-- ❌ `PublishingRecord.site_blueprint` - FK removed
-- ❌ `DeploymentRecord.site_blueprint` - FK removed
-
----
-
-## What Was Simplified
-
-### Taxonomy Architecture Change
-
-**Before (Complex):**
-```
-Content → ContentTaxonomyMap → ContentTaxonomy
- (through table with FK)
-```
-
-**After (Simple):**
-```
-Content ↔ ContentTaxonomy
-(many-to-many via ContentTaxonomyRelation)
-```
-
-**Files Changed:**
-1. `backend/igny8_core/business/content/models.py`
- - Added `Content.taxonomy_terms` M2M field
- - Through model: `ContentTaxonomyRelation`
-
-2. `backend/igny8_core/tasks/wordpress_publishing.py`
- - Updated to use `content.taxonomy_terms.filter(taxonomy_type='category')`
- - Updated to use `content.taxonomy_terms.filter(taxonomy_type='tag')`
-
-3. `backend/igny8_core/business/planning/services/candidate_engine.py`
- - Changed from `ContentTaxonomyMap.objects.filter(content=...)`
- - To: `content.taxonomy_terms.values_list('id', flat=True)`
-
----
-
-## Current System Architecture
-
-### ✅ Planner-Writer-Publisher Workflow (Intact)
-
-```
-1. PLANNER (Phase 1-3)
- Keywords → Clusters → Ideas
-
-2. WRITER (Phase 4)
- Ideas → Tasks → Content
-
-3. PUBLISHER (Phase 5)
- Content → WordPress/Sites
-```
-
-### ✅ Content Taxonomy Model
-
-**Location:** `backend/igny8_core/business/content/models.py`
-
-**Model: ContentTaxonomy**
-```python
-class ContentTaxonomy(SiteSectorBaseModel):
- # Core fields
- name CharField(255) # "Technology", "Tutorial"
- slug SlugField(255) # "technology", "tutorial"
- taxonomy_type CharField(50) # "category" or "tag"
- description TextField # Term description
- count IntegerField # Usage count
-
- # WordPress sync fields
- external_taxonomy CharField(100) # "category", "post_tag"
- external_id IntegerField # WordPress term_id
-
- # Metadata
- metadata JSONField # AI generation details
-
- # Relationships
- contents M2M(Content) # Related content
-```
-
-**Model: Content**
-```python
-class Content(SiteSectorBaseModel):
- # Core fields
- title CharField(255)
- content_html TextField
- word_count IntegerField
-
- # SEO
- meta_title CharField(255)
- meta_description TextField
- primary_keyword CharField(255)
- secondary_keywords JSONField
-
- # Relationships
- cluster FK(Clusters) # Required parent cluster
- taxonomy_terms M2M(ContentTaxonomy) # Categories & tags
-
- # Type/Structure
- content_type CharField(50) # post, page, product
- content_structure CharField(50) # article, guide, review, etc.
-
- # WordPress sync
- external_id CharField(255) # WordPress post ID
- external_url URLField # WordPress URL
- external_type CharField(100) # WordPress post type
- sync_status CharField(50) # Sync status
-
- # Source & Status
- source CharField(50) # igny8 or wordpress
- status CharField(50) # draft, review, published
-```
-
-**Through Model: ContentTaxonomyRelation**
-```python
-class ContentTaxonomyRelation(models.Model):
- content FK(Content)
- taxonomy FK(ContentTaxonomy)
- created_at DateTimeField
- updated_at DateTimeField
-
- unique_together = [['content', 'taxonomy']]
-```
-
----
-
-## WordPress Integration (Unchanged)
-
-### Bidirectional Sync Still Works
-
-**From IGNY8 → WordPress:**
-```python
-# File: backend/igny8_core/tasks/wordpress_publishing.py
-categories = [
- term.name
- for term in content.taxonomy_terms.filter(taxonomy_type='category')
-]
-tags = [
- term.name
- for term in content.taxonomy_terms.filter(taxonomy_type='tag')
-]
-```
-
-**From WordPress → IGNY8:**
-- WordPress plugin continues to sync content back
-- External IDs maintained in `Content.external_id` and `ContentTaxonomy.external_id`
-- Logging system intact: `[5-homeg8.com] [POST] ...`
-
----
-
-## Database Migration
-
-### Migration File Created
-**Location:** `backend/igny8_core/business/site_building/migrations/0002_remove_blueprint_models.py`
-
-**Operations:**
-1. Drop table: `site_building_siteblueprint`
-2. Drop table: `site_building_pageblueprint`
-3. Drop table: `site_building_siteblueprintcluster`
-4. Drop table: `site_building_siteblueprinttaxonomy`
-5. Remove FK: `publishing_publishingrecord.site_blueprint_id`
-6. Remove FK: `publishing_deploymentrecord.site_blueprint_id`
-
-### ⚠️ Migration Status: NOT YET APPLIED
-
-**Reason:** PostgreSQL database is external (not in docker-compose)
-
-**To Apply Manually:**
-```bash
-# Connect to your PostgreSQL database and run:
-cd /data/app/igny8/backend
-docker exec -it igny8_backend python manage.py migrate
-```
-
-**Or if manual SQL preferred:**
-```sql
--- Drop blueprint tables
-DROP TABLE IF EXISTS site_building_siteblueprinttaxonomy CASCADE;
-DROP TABLE IF EXISTS site_building_siteblueprintcluster CASCADE;
-DROP TABLE IF EXISTS site_building_pageblueprint CASCADE;
-DROP TABLE IF EXISTS site_building_siteblueprint CASCADE;
-
--- Remove foreign keys from publishing tables
-ALTER TABLE publishing_publishingrecord DROP COLUMN IF EXISTS site_blueprint_id;
-ALTER TABLE publishing_deploymentrecord DROP COLUMN IF EXISTS site_blueprint_id;
-```
-
----
-
-## Files Modified (24 Backend + 3 Frontend)
-
-### Backend Core
-1. `backend/igny8_core/settings.py` - Removed site_builder from INSTALLED_APPS
-2. `backend/igny8_core/business/site_building/models.py` - Emptied (placeholder comments only)
-3. `backend/igny8_core/business/site_building/admin.py` - Emptied
-4. `backend/igny8_core/business/publishing/models.py` - Removed site_blueprint FK
-5. `backend/igny8_core/business/publishing/services/publisher_service.py` - Removed blueprint methods
-6. `backend/igny8_core/modules/publisher/views.py` - Removed blueprint actions
-7. `backend/igny8_core/modules/publisher/serializers.py` - Fixed to use exclude=[]
-8. `backend/igny8_core/tasks/wordpress_publishing.py` - Updated to use M2M taxonomy
-
-### Backend Services
-9. `backend/igny8_core/business/planning/services/metadata_mapping_service.py` - Removed ContentTaxonomyMap import
-10. `backend/igny8_core/business/planning/services/candidate_engine.py` - Updated to use M2M taxonomy
-
-### Frontend
-11. `frontend/src/services/api.ts` - Removed SiteBlueprint interfaces/functions
-12. `frontend/src/modules/siteBuilder/` - **DELETED DIRECTORY**
-
----
-
-## Verification Steps Completed
-
-### ✅ Backend Health Check
-```bash
-$ docker ps --filter "name=igny8_backend"
-igny8_backend Up 27 seconds (healthy)
-```
-
-### ✅ Celery Worker Health
-```bash
-$ docker ps --filter "name=igny8_celery"
-igny8_celery_worker Up About a minute
-igny8_celery_beat Up 3 hours
-```
-
-### ✅ Backend Startup Logs
-```
-[2025-12-01 02:03:31] [INFO] Starting gunicorn 23.0.0
-[2025-12-01 02:03:31] [INFO] Listening at: http://0.0.0.0:8010
-[2025-12-01 02:03:31] [INFO] Using worker: sync
-[2025-12-01 02:03:31] [INFO] Booting worker with pid: 7
-[2025-12-01 02:03:31] [INFO] Booting worker with pid: 8
-[2025-12-01 02:03:31] [INFO] Booting worker with pid: 9
-[2025-12-01 02:03:31] [INFO] Booting worker with pid: 10
-```
-
-### ✅ No Import Errors
-No `NameError: name 'SiteBlueprint' is not defined` errors
-
----
-
-## Remaining References (Harmless)
-
-**Where:** site_building tests and services (not loaded)
-- `backend/igny8_core/business/site_building/tests/` - Test files (not executed)
-- `backend/igny8_core/business/site_building/services/` - Service files (not imported)
-- `backend/igny8_core/business/planning/models.py` - Comment only
-
-**Why Harmless:** site_builder module removed from INSTALLED_APPS so Django never loads these files.
-
----
-
-## Django Admin Access
-
-### ✅ ContentTaxonomy Available
-**URL:** `http://your-domain/admin/writer/contenttaxonomy/`
-
-**Features:**
-- Create/edit categories and tags
-- Set taxonomy_type (category/tag)
-- Configure WordPress sync (external_id, external_taxonomy)
-- View count and metadata
-
-### ✅ Content Available
-**URL:** `http://your-domain/admin/writer/content/`
-
-**Features:**
-- View all content
-- Edit taxonomy_terms M2M relationships
-- See cluster relationships
-- WordPress sync status
-
----
-
-## Next Steps (Optional)
-
-### 1. Apply Database Migration
-```bash
-docker exec -it igny8_backend python manage.py migrate
-```
-
-### 2. Clean Up Remaining Files (Optional)
-```bash
-# Remove site_building directory entirely if not needed for history
-rm -rf backend/igny8_core/business/site_building/
-
-# Or keep for git history but add .gitignore
-echo "backend/igny8_core/business/site_building/" >> .gitignore
-```
-
-### 3. Test WordPress Publishing
-1. Create test content in Django admin
-2. Assign categories/tags via taxonomy_terms M2M
-3. Publish to WordPress
-4. Verify categories/tags appear correctly
-5. Check sync logs: `backend/logs/publish-sync-logs/*.log`
-
----
-
-## Technical Notes
-
-### Python Bytecode Cache Issue Resolved
-**Problem:** Docker container cached old .pyc files with SiteBlueprint references
-**Solution:** Used `docker compose up -d --force-recreate igny8_backend` to clear cache
-
-### Import Structure Clean
-- No circular imports
-- No missing dependencies
-- All type hints cleaned from removed models
-
-### Multi-Tenant Architecture Intact
-```
-Account → Site → Sector → Content/Taxonomy
-```
-All models inherit from `SiteSectorBaseModel` with proper filtering.
-
----
-
-## Support
-
-For issues or questions about this removal:
-1. Check backend logs: `docker logs igny8_backend`
-2. Check celery logs: `docker logs igny8_celery_worker`
-3. Check publish logs: `backend/logs/publish-sync-logs/`
-4. Refer to: `docs/02-PLANNER-WRITER-WORKFLOW-TECHNICAL-GUIDE.md`
-
----
-
-**Summary:** All SiteBuilder/Blueprint functionality successfully removed. Backend healthy. WordPress publishing intact. Taxonomy simplified to direct M2M relationship. Migration file created but not yet applied.
diff --git a/STATUS-IMPLEMENTATION-TABLES.md b/docs/STATUS-IMPLEMENTATION-TABLES.md
similarity index 100%
rename from STATUS-IMPLEMENTATION-TABLES.md
rename to docs/STATUS-IMPLEMENTATION-TABLES.md
diff --git a/docs/future-docs/current-state.md b/docs/future-docs/current-state.md
deleted file mode 100644
index 845f6167..00000000
--- a/docs/future-docs/current-state.md
+++ /dev/null
@@ -1,116 +0,0 @@
-Understood fully.
-
-Everything you said in this entire session so far is now locked in as **active working context**.
-I will maintain every point precisely as you defined it, and nothing will be lost.
-
-Here is the **exact memory snapshot** of the current state, exactly as you described it.
-No assumptions. No additions. No explanations unless you ask.
-
----
-
-# **CURRENT STATE SNAPSHOT (Your Words, Consolidated Precisely)**
-
-### **1. System implementation state**
-
-* The IGNY8 app codebase is **95 percent implemented** based on the master docs you gave.
-* You are now finalizing cleanup and integration fixes.
-
-### **2. Removing deprecated modules**
-
-You are actively removing:
-
-* **Site Builder**
-* **Blueprints**
-* **Page Blueprints**
-* **Deployment readiness**
-* **Renderer**
-* All related frontend and backend code
-* All unnecessary taxonomy structures created for builder functions
-
-These removals are ongoing and being executed step by step through your AI agent in the IDE.
-
-### **3. Active focus now (your priority list)**
-
-1. **Remove Site Builder and Renderer completely**
-2. **Troubleshoot IGNY8 → WordPress Publishing issues**
-
-### **4. Publishing issues (current findings)**
-
-* WordPress post is created successfully.
-* **Categories not being applied**
-* **Tags not being applied**
-* **Images not being set as featured image**
-* Log shows:
-
-```
-⚠️ No categories in content_data
-⚠️ No tags in content_data
-⚠️ No featured image in content_data
-```
-
-### **5. Image issue**
-
-* Previous issue: image URL was pointing to provider instead of IGNY8 local storage.
-* You fixed the storage path code.
-* **Not tested yet**.
-
-### **6. Taxonomy issue**
-
-* WordPress categories and tags were not reaching the plugin because:
-
- * The internal IGNY8 `ContentTaxonomy` and builder-linked taxonomy model structure was overly complex.
- * Blueprint removal affects how taxonomies were originally mapped and injected.
-* You decided to clean up taxonomy code first *before* debugging publishing further.
-
-### **7. Real-time actions (from the screenshot)**
-
-Your AI agent is:
-
-* Removing frontend modules related to SiteBuilder.
-* Searching and deleting folders.
-* Cleaning routes and navigation.
-* Cleaning backend references (serializers, views, models).
-* Simplifying taxonomy and removing blueprint links inside planner/serializer logic.
-
-You are currently in the phase:
-**"Remove SiteBuilder from frontend 4/8"**
-and continuing cleanup in both frontend and backend.
-
-### **8. WordPress publishing log**
-
-The plugin logs confirm:
-
-* Title is passed correctly
-* Task ID missing (content was published without a task connection)
-* Categories missing
-* Tags missing
-* Featured image missing
-* SEO fields are applied correctly
-* Post created in draft status
-* URL returned correctly
-
-### **9. Expected behavior from me**
-
-You expect:
-
-* Full retention of every point you say.
-* No drifting.
-* No assumptions.
-* Conversational flow led **only by you**.
-* No detailed answers unless requested.
-* No large explanations.
-* You will give the direction, and I follow exactly.
-
-You also want:
-
-* All context remembered so we do not divert or make wrong assumptions.
-
----
-
-# **I confirm**
-
-All the points above are stored and will remain the active context for this session.
-
-No matter how long this session goes, I will maintain this exact working state and alignment.
-
-You can continue with the next instruction.
diff --git a/docs/future-docs/nex-plan.md b/docs/future-docs/nex-plan.md
deleted file mode 100644
index a378eece..00000000
--- a/docs/future-docs/nex-plan.md
+++ /dev/null
@@ -1,75 +0,0 @@
-Noted.
-Locked in as the next phase plan.
-
-Here is the **clean, precise, conversational summary** of what you want to work on next, without over-explaining anything.
-
----
-
-# **NEXT PLAN (AFTER CURRENT ISSUES ARE FIXED)**
-
-### These two items are now officially added to the working context.
-
----
-
-## **1. Site Delete Option (Critical, High-Risk Operation)**
-
-You want:
-
-* A **Delete Site** function in the frontend (Sites page).
-* It must include:
-
- * Safety guardrails
- * Clear irreversible warning
- * Possibly typing the site name to confirm
- * Only owner or power-user-level roles can delete
-* On delete:
-
- * **Every single record linked to that site** must be deleted from all tables.
- * Keywords → Clusters → Ideas → Tasks → Content → Images → Taxonomies → Automation rules → Any integration records
- * No orphaned data
- * No foreign key conflicts
-
-Basically:
-**Full cascading deletion of everything under that site.**
-
-This requires careful backend configuration and is a major integrity operation.
-
-This point is confirmed and stored.
-
----
-
-## **2. Django Backend: Proper Delete + Bulk Delete Support**
-
-You want:
-
-* Consistency across all modules
-* Every ViewSet must support:
-
- * Single record delete
- * Bulk delete
-* Only Admin or Power User can perform deletes
-* Delete must include:
-
- * Correct cascade behavior
- * Related-table cleanup
- * No dangling relations
-* Must be unified across:
-
- * Planner
- * Writer
- * Publisher
- * Billing
- * System
- * Integration
- * Automation
- * Sites, Sectors
-
-You want a **global, consistent delete pattern**, not current scattered behavior.
-
-This point is confirmed and stored.
-
----
-
-Both items are now stored as part of the active working context and will remain aligned throughout the session.
-
-Tell me how you want to proceed next.
diff --git a/docs/future-plan-to-remove-sites-site-builder-wrong-plan/SITES_DECISION_GUIDE.md b/docs/future-plan-to-remove-sites-site-builder-wrong-plan/SITES_DECISION_GUIDE.md
deleted file mode 100644
index d80ae118..00000000
--- a/docs/future-plan-to-remove-sites-site-builder-wrong-plan/SITES_DECISION_GUIDE.md
+++ /dev/null
@@ -1,424 +0,0 @@
-# Sites Container - Keep vs Remove Decision Guide
-
-**Version:** 1.0
-**Date:** November 29, 2025
-
----
-
-## Decision Tree
-
-```
-Do you need Site Builder & Sites Renderer features?
-│
-├─ NO → Remove everything (Option A: Full Removal)
-│ ├─ Delete /sites/ folder
-│ ├─ Delete /site-builder/ folder
-│ ├─ Remove backend modules
-│ ├─ Remove database tables
-│ └─ Clean up all references
-│
-└─ YES → Do you need separate container?
- │
- ├─ NO → Merge into frontend (Option B: Integration)
- │ ├─ Copy files to /frontend/
- │ ├─ Update routes in App.tsx
- │ ├─ Remove /sites/ container
- │ └─ Keep backend modules
- │
- └─ YES → Keep current setup (Option C: No Changes)
- ├─ Keep /sites/ container running
- ├─ Keep separate ports (8021, 8024)
- └─ Maintain current architecture
-```
-
----
-
-## Option A: Full Removal (No Site Features)
-
-### When to Choose
-- ✅ You don't need site blueprint creation
-- ✅ You don't need public site rendering
-- ✅ You only need WordPress publishing (direct to WP)
-- ✅ You want minimal feature set
-
-### What Gets Removed
-
-#### Frontend
-```bash
-# Remove folders
-rm -rf /sites/
-rm -rf /site-builder/
-rm -rf /frontend/src/modules/siteBuilder/
-rm -rf /frontend/src/pages/Sites/ # if exists
-rm -rf /frontend/src/components/sites/ # site-specific only
-
-# Remove from docker-compose
-# Delete igny8_sites service
-```
-
-#### Backend
-```bash
-# Remove modules
-rm -rf backend/igny8_core/modules/site_builder/
-rm -rf backend/igny8_core/modules/publisher/ # Only if not using WP publish
-
-# Remove business logic
-rm -rf backend/igny8_core/business/site_building/
-rm -rf backend/igny8_core/business/publishing/ # Be careful - WP uses this
-
-# Update settings.py - remove from INSTALLED_APPS
-# 'igny8_core.modules.site_builder',
-```
-
-#### Database
-```sql
--- Drop tables (CAREFUL - NO UNDO)
-DROP TABLE site_builder_siteblueprint CASCADE;
-DROP TABLE site_builder_sitepage CASCADE;
-DROP TABLE site_builder_taxonomy CASCADE;
-DROP TABLE site_builder_cluster_blueprints CASCADE;
--- etc.
-```
-
-#### URLs
-```python
-# In backend/igny8_core/urls.py
-# Remove:
-# path('api/v1/site-builder/', include('igny8_core.modules.site_builder.urls')),
-# path('api/v1/publisher/sites//definition/', ...)
-```
-
-### Files to Update
-
-| File | Changes |
-|------|---------|
-| `docker-compose.app.yml` | Remove igny8_sites service |
-| `backend/igny8_core/settings.py` | Remove site_builder from INSTALLED_APPS |
-| `backend/igny8_core/urls.py` | Remove site-builder URL patterns |
-| `frontend/src/App.tsx` | Remove site-related routes |
-| `frontend/src/components/sidebar/AppSidebar.tsx` | Remove site builder menu |
-| `frontend/package.json` | Remove site-builder dependencies (if any) |
-| `docs/MASTER_REFERENCE.md` | Update architecture section |
-
-### Impact
-- ❌ No site blueprint creation
-- ❌ No public site rendering
-- ✅ WordPress publishing still works (if using direct WP API)
-- ✅ Smaller codebase
-- ✅ Fewer containers
-- ✅ Simpler deployment
-
-### Rollback Difficulty
-🔴 **HARD** - Database tables deleted, requires full backup restore
-
----
-
-## Option B: Merge Into Frontend (Recommended)
-
-### When to Choose
-- ✅ You need site builder features
-- ✅ You need public site rendering
-- ✅ You want simpler deployment
-- ✅ You want unified authentication
-- ✅ Sites are internal or low-traffic
-
-### What Changes
-
-#### Keep These (Backend)
-```
-backend/igny8_core/
-├── modules/
-│ ├── site_builder/ ✅ KEEP
-│ └── publisher/ ✅ KEEP
-├── business/
-│ ├── site_building/ ✅ KEEP
-│ └── publishing/ ✅ KEEP
-└── Database tables ✅ KEEP ALL
-```
-
-#### Move These (Frontend)
-```
-/sites/src/ → /frontend/src/pages/Sites/
-/sites/src/builder/ → /frontend/src/pages/Sites/Builder/
-/sites/src/utils/ → /frontend/src/utils/siteRenderer/
-```
-
-#### Delete These
-```
-/sites/ folder (after copying)
-/site-builder/ folder
-/frontend/src/modules/siteBuilder/ (empty)
-igny8_sites Docker container
-```
-
-### Files to Update
-
-| File | Type | Changes |
-|------|------|---------|
-| `frontend/src/App.tsx` | **UPDATE** | Add site builder & renderer routes |
-| `frontend/src/services/siteRenderer.api.ts` | **CREATE** | Site renderer API client |
-| `frontend/vite.config.ts` | **UPDATE** | Add SITES_DATA_PATH env |
-| `docker-compose.app.yml` | **UPDATE** | Remove igny8_sites, update igny8_frontend |
-| `backend/igny8_core/settings.py` | **VERIFY** | CORS settings (minor) |
-
-### Step-by-Step Guide
-📖 **See:** [SITES_REMOVAL_GUIDE.md](./SITES_REMOVAL_GUIDE.md) - Complete instructions
-
-### Impact
-- ✅ Site builder still works (routes change)
-- ✅ Public site rendering still works (routes change)
-- ✅ Backend unchanged (100% compatible)
-- ⚠️ Public site URLs change (update links)
-- ✅ Fewer containers (simpler deployment)
-- ✅ Unified authentication
-
-### Rollback Difficulty
-🟡 **MEDIUM** - Can restore from backup, backend unchanged
-
----
-
-## Option C: Keep Separate Container
-
-### When to Choose
-- ✅ You need performance isolation for public sites
-- ✅ You want to scale sites independently
-- ✅ You have high-traffic public sites
-- ✅ You want different deployment schedules
-- ✅ Current setup works fine
-
-### What Changes
-**Nothing!** Keep current architecture.
-
-### Files to Update
-**None** - No changes needed
-
-### Maintenance
-- Keep `/sites/` folder
-- Keep `igny8_sites` container running
-- Keep port 8024 accessible
-- Maintain separate Docker image
-
-### Impact
-- ✅ No migration risk
-- ✅ Performance isolation
-- ✅ Independent scaling
-- ❌ More containers to manage
-- ❌ More complex deployment
-
-### Rollback Difficulty
-🟢 **EASY** - Already the current state
-
----
-
-## Comparison Matrix
-
-| Aspect | Option A: Full Removal | Option B: Merge to Frontend | Option C: Keep Separate |
-|--------|----------------------|---------------------------|------------------------|
-| **Containers** | 1 (frontend only) | 2 (frontend + backend) | 3 (frontend + sites + backend) |
-| **Site Builder** | ❌ Removed | ✅ In frontend | ✅ In sites container |
-| **Site Renderer** | ❌ Removed | ✅ In frontend | ✅ In sites container |
-| **Backend API** | ❌ Removed | ✅ Kept | ✅ Kept |
-| **Database** | ❌ Dropped | ✅ Kept | ✅ Kept |
-| **Ports** | 8021 only | 8021 only | 8021, 8024 |
-| **Deployment** | Simple | Simple | Complex |
-| **Rollback** | Hard | Medium | Easy |
-| **Performance** | N/A | Good | Best (isolated) |
-| **Complexity** | Low | Medium | High |
-| **Recommended For** | Minimal setup | Most users | High-traffic sites |
-
----
-
-## Migration Difficulty
-
-### Option A: Full Removal
-```
-Difficulty: ████████░░ 80%
-Time: 6-8 hours
-Risk: HIGH (data loss)
-Rollback: HARD (requires backup)
-```
-
-**Steps:**
-1. Backup database
-2. Remove frontend folders
-3. Remove backend modules
-4. Drop database tables
-5. Update URLs and settings
-6. Remove Docker services
-7. Update all documentation
-
-### Option B: Merge to Frontend
-```
-Difficulty: ██████░░░░ 60%
-Time: 5-6 hours
-Risk: MEDIUM (UI changes)
-Rollback: MEDIUM (restore backup)
-```
-
-**Steps:**
-1. Backup files
-2. Copy frontend files
-3. Update routes
-4. Update Docker config
-5. Test functionality
-6. Remove old container
-7. Update documentation
-
-### Option C: Keep Separate
-```
-Difficulty: ░░░░░░░░░░ 0%
-Time: 0 hours
-Risk: NONE
-Rollback: N/A (no changes)
-```
-
-**Steps:**
-1. None - keep current setup
-
----
-
-## Recommendation by Use Case
-
-### For Development/Testing
-**→ Option B: Merge to Frontend**
-- Simpler setup
-- Easier debugging
-- Fewer containers
-- Faster iteration
-
-### For Small Production (<100 sites)
-**→ Option B: Merge to Frontend**
-- Good performance
-- Simpler deployment
-- Lower resource usage
-- Easier maintenance
-
-### For Large Production (>100 sites, high traffic)
-**→ Option C: Keep Separate**
-- Performance isolation
-- Independent scaling
-- Better resource management
-- Fault isolation
-
-### For Minimal Setup (No site features needed)
-**→ Option A: Full Removal**
-- Smallest footprint
-- Lowest complexity
-- Minimal maintenance
-- Only if truly not needed
-
----
-
-## Red Flags - Don't Remove If:
-
-🚫 **Don't choose Option A if:**
-- You have existing site blueprints in database
-- You're actively using site builder
-- You publish to sites renderer (not just WordPress)
-- You're unsure if you'll need it later
-
-🚫 **Don't choose Option B if:**
-- You have high-traffic public sites (>10k visits/day)
-- You need to scale sites independently
-- You have strict performance requirements
-- You want to deploy sites on different infrastructure
-
-🚫 **Don't choose Option C if:**
-- You're struggling with too many containers
-- You want simpler deployment
-- You have low-traffic sites
-- You value simplicity over isolation
-
----
-
-## Safe Path Forward
-
-### Recommended Approach
-
-1. **Start with Option C** (Keep separate) ← You are here
-2. **Evaluate for 30 days**
- - Monitor site traffic
- - Check resource usage
- - Assess deployment complexity
-3. **If low traffic/simple needs** → **Move to Option B** (Merge)
-4. **If high traffic/complex needs** → **Stay with Option C** (Keep separate)
-5. **If features unused** → **Consider Option A** (Remove)
-
-### Safe Testing Strategy
-
-```bash
-# 1. Test Option B in parallel (non-destructive)
-# Keep sites container running on port 8024
-# Deploy merged version on port 8021
-# Compare functionality side-by-side
-
-# 2. If Option B works well
-# Switch traffic gradually
-# Monitor for issues
-
-# 3. After 30 days of stability
-# Remove sites container (Option B complete)
-```
-
----
-
-## Decision Criteria
-
-### Choose Option A (Full Removal) If:
-- [ ] No existing site blueprints in database
-- [ ] No plans to use site builder ever
-- [ ] Only using WordPress publishing (direct)
-- [ ] Want absolute minimal setup
-
-### Choose Option B (Merge to Frontend) If:
-- [x] Need site builder features
-- [x] Have low-medium traffic sites
-- [x] Want simpler deployment
-- [x] Prefer fewer containers
-- [x] Sites are mostly internal
-
-### Choose Option C (Keep Separate) If:
-- [ ] High-traffic public sites
-- [ ] Need performance isolation
-- [ ] Want independent scaling
-- [ ] Current setup works well
-- [ ] Have complex requirements
-
----
-
-## Next Steps Based on Choice
-
-### If Choosing Option A:
-1. Read [SITES_REMOVAL_GUIDE.md](./SITES_REMOVAL_GUIDE.md) Section: "Full Removal"
-2. Backup database completely
-3. Export any site data you want to keep
-4. Follow removal checklist
-5. Test thoroughly
-
-### If Choosing Option B:
-1. Read [SITES_REMOVAL_GUIDE.md](./SITES_REMOVAL_GUIDE.md) - Full guide
-2. Read [SITES_REMOVAL_QUICK_REFERENCE.md](./SITES_REMOVAL_QUICK_REFERENCE.md) - Quick commands
-3. Backup files and database
-4. Follow Phase 1-7 in guide
-5. Test thoroughly before cleanup
-
-### If Choosing Option C:
-1. No action needed
-2. Continue with current setup
-3. Maintain both containers
-4. Keep documentation updated
-
----
-
-## Support Documentation
-
-- **Full Removal & Integration Guide:** [SITES_REMOVAL_GUIDE.md](./SITES_REMOVAL_GUIDE.md)
-- **Quick Reference:** [SITES_REMOVAL_QUICK_REFERENCE.md](./SITES_REMOVAL_QUICK_REFERENCE.md)
-- **System Architecture:** [MASTER_REFERENCE.md](./MASTER_REFERENCE.md)
-- **API Reference:** [API-COMPLETE-REFERENCE.md](./API-COMPLETE-REFERENCE.md)
-
----
-
-**Recommendation:** Start with **Option C** (current state), evaluate needs, then move to **Option B** if appropriate.
-
-**Last Updated:** November 29, 2025
diff --git a/docs/future-plan-to-remove-sites-site-builder-wrong-plan/SITES_REMOVAL_GUIDE.md b/docs/future-plan-to-remove-sites-site-builder-wrong-plan/SITES_REMOVAL_GUIDE.md
deleted file mode 100644
index 7c4d283b..00000000
--- a/docs/future-plan-to-remove-sites-site-builder-wrong-plan/SITES_REMOVAL_GUIDE.md
+++ /dev/null
@@ -1,743 +0,0 @@
-# Sites & Site Builder Removal Guide
-
-**Version:** 1.0
-**Date:** November 29, 2025
-**Purpose:** Complete guide to remove separate sites/site-builder containers and integrate functionality into main frontend app
-
----
-
-## Executive Summary
-
-This document provides a **safe, step-by-step process** to:
-1. Remove the `/sites/` container and folder
-2. Remove the `/site-builder/` folder (already empty/deprecated)
-3. Integrate Sites Renderer and Site Builder features into the main `/frontend/` application
-4. Update all affected components, configurations, and documentation
-
-**Current State:**
-- 3 separate containers: `igny8_frontend`, `igny8_sites`, `igny8_marketing_dev`
-- Site Builder UI in separate `/sites/` container (port 8024)
-- Sites Renderer in separate `/sites/` container (port 8024)
-
-**Target State:**
-- 2 containers: `igny8_frontend`, `igny8_marketing_dev`
-- Site Builder UI integrated into main frontend
-- Sites Renderer integrated into main frontend
-- Single unified application on port 8021
-
----
-
-## Impact Analysis
-
-### Features That Will Be Affected
-
-#### 1. **Site Blueprint Management** (Site Builder)
-**Current Location:** `/sites/src/builder/`
-**Current Routes:** `/builder/*` (separate container)
-**Functionality:**
-- Site structure wizard
-- Blueprint creation and management
-- Preview canvas for site layouts
-- Blueprint history dashboard
-
-**Backend Dependencies:**
-- API: `/api/v1/site-builder/blueprints/`
-- Module: `backend/igny8_core/modules/site_builder/`
-- Business Logic: `backend/igny8_core/business/site_building/`
-
-**Impact:** Medium - Needs route integration into main app
-
----
-
-#### 2. **Sites Renderer** (Public Site Viewing)
-**Current Location:** `/sites/src/pages/SiteRenderer.tsx`
-**Current Routes:** `/:siteSlug/:pageSlug?` (separate container)
-**Functionality:**
-- Loads site definitions from `/data/app/sites-data/`
-- Renders published sites for public viewing
-- No authentication required
-
-**Backend Dependencies:**
-- API: `/api/v1/publisher/sites/{site_id}/definition/`
-- Service: `backend/igny8_core/business/publishing/services/adapters/sites_renderer_adapter.py`
-- Data: `/data/app/sites-data/clients/{site_id}/v{version}/`
-
-**Impact:** High - Public-facing feature, needs careful route handling
-
----
-
-#### 3. **Backend Modules** (Keep These)
-**Modules to Keep:**
-```
-backend/igny8_core/
-├── modules/
-│ ├── site_builder/ ✅ KEEP (API endpoints)
-│ └── publisher/ ✅ KEEP (publishing logic)
-└── business/
- ├── site_building/ ✅ KEEP (business logic)
- └── publishing/ ✅ KEEP (renderer adapter)
-```
-
-**Rationale:** Backend functionality is used by the main frontend app, just changing the UI container.
-
----
-
-## Removal & Integration Plan
-
-### Phase 1: Preparation & Backup
-
-#### Step 1.1: Create Backup
-```bash
-# Backup current state
-cd /data/app/igny8
-tar -czf backup-sites-$(date +%Y%m%d-%H%M%S).tar.gz sites/ site-builder/
-
-# Backup docker-compose
-cp docker-compose.app.yml docker-compose.app.yml.backup
-
-# Verify backup
-ls -lh backup-sites-*.tar.gz
-```
-
-#### Step 1.2: Document Current Routes
-```bash
-# Document current running containers
-docker ps | grep igny8 > current-containers.txt
-
-# Test current site builder access
-curl -I http://localhost:8024/builder/
-
-# Test current sites renderer
-curl -I http://localhost:8024/
-```
-
----
-
-### Phase 2: Frontend Integration
-
-#### Step 2.1: Copy Site Builder Components to Frontend
-
-**Source:** `/sites/src/builder/`
-**Destination:** `/frontend/src/pages/Sites/`
-
-```bash
-cd /data/app/igny8
-
-# Create target directory
-mkdir -p frontend/src/pages/Sites/Builder
-
-# Copy builder components
-cp -r sites/src/builder/pages/* frontend/src/pages/Sites/Builder/
-cp -r sites/src/builder/components/* frontend/src/components/sites/builder/
-
-# Copy shared types if needed
-cp sites/src/types/index.ts frontend/src/types/siteBuilder.types.ts
-```
-
-**Files to Copy:**
-```
-sites/src/builder/
-├── pages/
-│ ├── wizard/
-│ │ └── WizardPage.tsx → frontend/src/pages/Sites/Builder/Wizard.tsx
-│ ├── preview/
-│ │ └── PreviewCanvas.tsx → frontend/src/pages/Sites/Builder/Preview.tsx
-│ └── dashboard/
-│ └── SiteDashboard.tsx → frontend/src/pages/Sites/Builder/Dashboard.tsx
-└── components/
- └── layout/
- └── BuilderLayout.tsx → frontend/src/components/sites/BuilderLayout.tsx
-```
-
----
-
-#### Step 2.2: Copy Sites Renderer to Frontend
-
-**Source:** `/sites/src/pages/SiteRenderer.tsx`
-**Destination:** `/frontend/src/pages/Sites/`
-
-```bash
-# Copy renderer components
-cp sites/src/pages/SiteRenderer.tsx frontend/src/pages/Sites/PublicSiteRenderer.tsx
-cp sites/src/loaders/loadSiteDefinition.ts frontend/src/services/siteRenderer.api.ts
-cp -r sites/src/utils/* frontend/src/utils/siteRenderer/
-```
-
-**Files to Copy:**
-```
-sites/src/
-├── pages/
-│ └── SiteRenderer.tsx → frontend/src/pages/Sites/PublicSiteRenderer.tsx
-├── loaders/
-│ └── loadSiteDefinition.ts → frontend/src/services/siteRenderer.api.ts
-└── utils/
- ├── layoutRenderer.tsx → frontend/src/utils/siteRenderer/layoutRenderer.tsx
- ├── pageTypeRenderer.tsx → frontend/src/utils/siteRenderer/pageTypeRenderer.tsx
- └── templateEngine.tsx → frontend/src/utils/siteRenderer/templateEngine.tsx
-```
-
----
-
-#### Step 2.3: Update Frontend Routes
-
-**File:** `/frontend/src/App.tsx`
-
-**Add these imports:**
-```tsx
-// Site Builder pages
-const SiteBuilderWizard = lazy(() => import("./pages/Sites/Builder/Wizard"));
-const SiteBuilderPreview = lazy(() => import("./pages/Sites/Builder/Preview"));
-const SiteBuilderDashboard = lazy(() => import("./pages/Sites/Builder/Dashboard"));
-
-// Public Sites Renderer
-const PublicSiteRenderer = lazy(() => import("./pages/Sites/PublicSiteRenderer"));
-```
-
-**Add these routes:**
-```tsx
-{/* Site Builder Routes - Protected */}
-
-
-
-
-
- }
-/>
-
-
-
-
-
- }
-/>
-
-
-
-
-
- }
-/>
-
-{/* Public Sites Renderer - No Auth Required */}
-} />
-```
-
-**Note:** Public renderer routes changed from `/:siteSlug/*` to `/sites/view/:siteSlug/*` to avoid route conflicts.
-
----
-
-#### Step 2.4: Update API Client for Sites Data
-
-**File:** `/frontend/src/services/siteRenderer.api.ts`
-
-**Update the API URL resolution:**
-```typescript
-function getApiBaseUrl(): string {
- // Use environment variable
- const envUrl = import.meta.env.VITE_API_URL || import.meta.env.VITE_BACKEND_URL;
- if (envUrl) {
- return envUrl.endsWith('/api') ? envUrl : `${envUrl}/api`;
- }
-
- // Auto-detect based on current origin
- if (typeof window !== 'undefined') {
- const origin = window.location.origin;
-
- // If accessing via IP, use backend port 8011
- if (/^\d+\.\d+\.\d+\.\d+/.test(origin) || origin.includes('localhost')) {
- return origin.replace(':8021', ':8011') + '/api';
- }
- }
-
- // Production: use subdomain
- return 'https://api.igny8.com/api';
-}
-```
-
----
-
-#### Step 2.5: Update Navigation Menu
-
-**File:** `/frontend/src/components/sidebar/AppSidebar.tsx` or navigation component
-
-**Add Site Builder menu item:**
-```tsx
-{
- title: "Site Builder",
- icon: ,
- items: [
- { title: "New Blueprint", path: "/sites/builder" },
- { title: "Preview", path: "/sites/builder/preview" },
- { title: "History", path: "/sites/builder/dashboard" },
- ],
-}
-```
-
----
-
-### Phase 3: Docker Configuration Updates
-
-#### Step 3.1: Update docker-compose.app.yml
-
-**File:** `/docker-compose.app.yml`
-
-**Remove the igny8_sites service:**
-```yaml
-# REMOVE THIS ENTIRE SERVICE:
- # igny8_sites:
- # image: igny8-sites-dev:latest
- # container_name: igny8_sites
- # restart: always
- # ports:
- # - "0.0.0.0:8024:5176"
- # environment:
- # VITE_API_URL: "https://api.igny8.com/api"
- # SITES_DATA_PATH: "/sites"
- # volumes:
- # - /data/app/igny8/sites:/app:rw
- # - /data/app/sites-data:/sites:ro
- # - /data/app/igny8/frontend:/frontend:ro
- # networks: [igny8_net]
-```
-
-**Update igny8_frontend service to access sites-data:**
-```yaml
- igny8_frontend:
- image: igny8-frontend-dev:latest
- container_name: igny8_frontend
- restart: always
- ports:
- - "0.0.0.0:8021:5173"
- environment:
- VITE_BACKEND_URL: "https://api.igny8.com/api"
- SITES_DATA_PATH: "/sites" # ADD THIS
- volumes:
- - /data/app/igny8/frontend:/app:rw
- - /data/app/sites-data:/sites:ro # ADD THIS - Read-only access to sites data
- depends_on:
- igny8_backend:
- condition: service_healthy
- networks: [igny8_net]
-```
-
----
-
-#### Step 3.2: Update Vite Configuration
-
-**File:** `/frontend/vite.config.ts`
-
-**Add environment variable for sites data path:**
-```typescript
-export default defineConfig({
- // ... existing config
- define: {
- 'import.meta.env.SITES_DATA_PATH': JSON.stringify(
- process.env.SITES_DATA_PATH || '/sites'
- ),
- },
- // ... rest of config
-});
-```
-
----
-
-### Phase 4: Backend Updates (Minor)
-
-#### Step 4.1: Update CORS Settings (if needed)
-
-**File:** `/backend/igny8_core/settings.py`
-
-**Verify CORS allows frontend port:**
-```python
-CORS_ALLOWED_ORIGINS = [
- 'http://localhost:5173', # Frontend dev server
- 'http://localhost:8021', # Frontend external port
- 'https://app.igny8.com',
- # Remove: 'http://localhost:8024', # Old sites container
-]
-```
-
----
-
-#### Step 4.2: Update Site Definition API (Optional Enhancement)
-
-**File:** `/backend/igny8_core/modules/publisher/views.py`
-
-**No changes required** - API already works, just being called from different container.
-
-**Optional:** Add CORS header for public site renderer if needed:
-```python
-from rest_framework.decorators import api_view, permission_classes
-from rest_framework.permissions import AllowAny
-
-@api_view(['GET'])
-@permission_classes([AllowAny]) # Public endpoint
-def get_site_definition(request, site_id):
- # ... existing code
-```
-
----
-
-### Phase 5: Testing & Verification
-
-#### Step 5.1: Build Updated Frontend
-```bash
-cd /data/app/igny8/frontend
-
-# Install any new dependencies (if added)
-npm install
-
-# Build to verify no errors
-npm run build
-
-# Rebuild Docker image
-cd /data/app/igny8/frontend
-docker build -t igny8-frontend-dev:latest -f Dockerfile.dev .
-```
-
----
-
-#### Step 5.2: Stop Old Container
-```bash
-# Stop and remove sites container
-docker stop igny8_sites
-docker rm igny8_sites
-
-# Verify it's stopped
-docker ps | grep sites
-```
-
----
-
-#### Step 5.3: Start Updated Stack
-```bash
-cd /data/app/igny8
-
-# Start with updated docker-compose
-docker compose -f docker-compose.app.yml up -d igny8_frontend
-
-# Check logs
-docker logs -f igny8_frontend
-```
-
----
-
-#### Step 5.4: Test Functionality
-
-**Test Site Builder:**
-```bash
-# Test builder routes (should require auth)
-curl -I http://localhost:8021/sites/builder
-
-# Test in browser:
-# http://localhost:8021/sites/builder (wizard)
-# http://localhost:8021/sites/builder/preview
-# http://localhost:8021/sites/builder/dashboard
-```
-
-**Test Sites Renderer:**
-```bash
-# Test public site renderer
-curl -I http://localhost:8021/sites/view/test-site
-
-# Test in browser:
-# http://localhost:8021/sites/view/{siteSlug}
-# http://localhost:8021/sites/view/{siteSlug}/{pageSlug}
-```
-
-**Test Existing API:**
-```bash
-# Verify site builder API still works
-curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
- http://localhost:8011/api/v1/site-builder/blueprints/
-
-# Verify site definition API
-curl http://localhost:8011/api/v1/publisher/sites/1/definition/
-```
-
----
-
-### Phase 6: Cleanup
-
-#### Step 6.1: Remove Folders (After Verification)
-
-**Only after confirming everything works:**
-```bash
-cd /data/app/igny8
-
-# Remove sites folder
-rm -rf sites/
-
-# Remove site-builder folder (already empty)
-rm -rf site-builder/
-
-# Remove empty frontend module
-rm -rf frontend/src/modules/siteBuilder/
-
-# Verify removal
-ls -la | grep -E "site-builder|sites"
-```
-
----
-
-#### Step 6.2: Remove Docker Image (Optional)
-```bash
-# Remove unused sites image
-docker rmi igny8-sites-dev:latest
-
-# Verify
-docker images | grep sites
-```
-
----
-
-#### Step 6.3: Clean Up Build Instructions
-
-**File:** `/docker-compose.app.yml` (comments at top)
-
-**Remove this line:**
-```yaml
-# Remove:
-# cd /data/app/igny8/sites && docker build -t igny8-sites-dev:latest -f Dockerfile.dev .
-```
-
----
-
-### Phase 7: Update Documentation
-
-#### Step 7.1: Update Files List
-
-**Files to update:**
-
-1. **README.md**
- - Remove references to `/sites/` container
- - Update port mapping (remove 8024)
- - Update build instructions
-
-2. **CHANGELOG.md**
- - Add entry: "Merged Sites & Site Builder into main frontend app"
-
-3. **docs/MASTER_REFERENCE.md**
- - Update architecture diagram
- - Remove igny8_sites container reference
- - Update route documentation
-
-4. **docs/API-COMPLETE-REFERENCE.md**
- - Update base URLs if needed
- - Verify endpoint documentation
-
----
-
-#### Step 7.2: Update Architecture Diagram
-
-**In MASTER_REFERENCE.md, update:**
-
-**OLD:**
-```
-┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
-│ Frontend (8021) │ │ Sites (8024) │ │ Backend (8011) │
-└──────────────────┘ └──────────────────┘ └──────────────────┘
-```
-
-**NEW:**
-```
-┌──────────────────┐ ┌──────────────────┐
-│ Frontend (8021) │ │ Backend (8011) │
-│ - Main App │ │ - Django API │
-│ - Site Builder │ │ - Celery │
-│ - Site Renderer │ │ │
-└──────────────────┘ └──────────────────┘
-```
-
----
-
-## Files & Folders Impact Summary
-
-### Files to Modify
-
-| File | Action | Reason |
-|------|--------|--------|
-| `/frontend/src/App.tsx` | **UPDATE** | Add site builder and renderer routes |
-| `/frontend/src/services/siteRenderer.api.ts` | **CREATE** | Site renderer API client |
-| `/frontend/src/pages/Sites/Builder/` | **CREATE** | Copy from sites/src/builder/ |
-| `/frontend/src/components/sites/builder/` | **CREATE** | Builder components |
-| `/frontend/vite.config.ts` | **UPDATE** | Add SITES_DATA_PATH env var |
-| `/docker-compose.app.yml` | **UPDATE** | Remove igny8_sites service |
-| `/backend/igny8_core/settings.py` | **VERIFY** | CORS settings (minor) |
-| `/README.md` | **UPDATE** | Architecture docs |
-| `/docs/MASTER_REFERENCE.md` | **UPDATE** | Remove sites container refs |
-
----
-
-### Files to Delete (After Verification)
-
-| File/Folder | Safe to Delete | Notes |
-|-------------|----------------|-------|
-| `/sites/` | ✅ YES | After copying to frontend |
-| `/site-builder/` | ✅ YES | Already empty |
-| `/frontend/src/modules/siteBuilder/` | ✅ YES | Empty folders |
-| `docker-compose.app.yml.backup` | ✅ YES | After successful migration |
-| `backup-sites-*.tar.gz` | ⚠️ KEEP | Keep for 30 days as rollback |
-
----
-
-### Backend Files - NO CHANGES NEEDED
-
-**These stay exactly as they are:**
-```
-backend/igny8_core/
-├── modules/
-│ ├── site_builder/ ✅ KEEP - No changes
-│ └── publisher/ ✅ KEEP - No changes
-├── business/
-│ ├── site_building/ ✅ KEEP - No changes
-│ └── publishing/ ✅ KEEP - No changes
-└── api/
- └── wordpress_publishing.py ✅ KEEP - No changes
-```
-
-**Rationale:** Backend APIs remain unchanged; only the frontend UI container changes.
-
----
-
-## Rollback Plan
-
-If issues occur, rollback is simple:
-
-### Option 1: Quick Rollback (Docker)
-```bash
-# Restore backup docker-compose
-cp docker-compose.app.yml.backup docker-compose.app.yml
-
-# Restart sites container
-docker compose -f docker-compose.app.yml up -d igny8_sites
-
-# Verify
-docker ps | grep sites
-curl -I http://localhost:8024/
-```
-
----
-
-### Option 2: Full Rollback (Restore Files)
-```bash
-# Extract backup
-cd /data/app/igny8
-tar -xzf backup-sites-YYYYMMDD-HHMMSS.tar.gz
-
-# Rebuild image
-cd sites
-docker build -t igny8-sites-dev:latest -f Dockerfile.dev .
-
-# Restart
-docker compose -f docker-compose.app.yml up -d igny8_sites
-```
-
----
-
-## Migration Checklist
-
-**Pre-Migration:**
-- [ ] Backup `/sites/` folder
-- [ ] Backup `/docker-compose.app.yml`
-- [ ] Document current container ports
-- [ ] Test current site builder functionality
-- [ ] Test current sites renderer functionality
-
-**Migration Steps:**
-- [ ] Copy site builder components to `/frontend/src/pages/Sites/Builder/`
-- [ ] Copy sites renderer to `/frontend/src/pages/Sites/PublicSiteRenderer.tsx`
-- [ ] Copy utilities to `/frontend/src/utils/siteRenderer/`
-- [ ] Update `/frontend/src/App.tsx` with new routes
-- [ ] Create `/frontend/src/services/siteRenderer.api.ts`
-- [ ] Update `/frontend/vite.config.ts`
-- [ ] Update `/docker-compose.app.yml` (remove igny8_sites, update igny8_frontend)
-- [ ] Rebuild frontend Docker image
-- [ ] Stop igny8_sites container
-- [ ] Start updated igny8_frontend container
-
-**Testing:**
-- [ ] Test site builder wizard at `/sites/builder`
-- [ ] Test site builder preview at `/sites/builder/preview`
-- [ ] Test site builder dashboard at `/sites/builder/dashboard`
-- [ ] Test public site renderer at `/sites/view/{siteSlug}`
-- [ ] Verify API calls work from frontend
-- [ ] Check browser console for errors
-- [ ] Test with authenticated user
-- [ ] Test without authentication (public renderer)
-
-**Post-Migration:**
-- [ ] Verify all tests pass
-- [ ] Update documentation (README, MASTER_REFERENCE)
-- [ ] Remove `/sites/` folder
-- [ ] Remove `/site-builder/` folder
-- [ ] Remove empty `/frontend/src/modules/siteBuilder/`
-- [ ] Remove Docker image `igny8-sites-dev:latest`
-- [ ] Keep backup for 30 days
-- [ ] Update portable package documentation
-
----
-
-## FAQ
-
-### Q: Will this break existing site blueprints?
-**A:** No. Backend database and APIs remain unchanged. Only the UI container changes.
-
-### Q: What about published sites in `/data/app/sites-data/`?
-**A:** They remain accessible. The frontend will mount `/sites-data` and load from there.
-
-### Q: Do I need to update WordPress integration?
-**A:** No. WordPress talks to backend API, which doesn't change.
-
-### Q: What if I want to keep sites as separate container?
-**A:** Keep current setup. This migration is optional for simplification.
-
-### Q: Will public site URLs change?
-**A:** Yes, from `http://localhost:8024/:siteSlug` to `http://localhost:8021/sites/view/:siteSlug`. Update any hardcoded links.
-
-### Q: Can I run both containers during transition?
-**A:** Yes, for testing. Run sites on 8024 and updated frontend on 8021, compare functionality.
-
----
-
-## Support & Troubleshooting
-
-### Issue: Routes not working after migration
-**Solution:** Check route order in `App.tsx`. Public renderer routes should be after protected routes.
-
-### Issue: API calls failing
-**Solution:** Verify `VITE_BACKEND_URL` in environment and check CORS settings.
-
-### Issue: Sites data not loading
-**Solution:** Verify `/data/app/sites-data` is mounted in docker-compose frontend service.
-
-### Issue: Build errors
-**Solution:** Run `npm install` to ensure dependencies match between sites and frontend.
-
----
-
-## Timeline Estimate
-
-| Phase | Time | Complexity |
-|-------|------|------------|
-| Phase 1: Preparation | 30 min | Low |
-| Phase 2: Frontend Integration | 2-3 hours | Medium |
-| Phase 3: Docker Updates | 30 min | Low |
-| Phase 4: Backend Updates | 15 min | Low |
-| Phase 5: Testing | 1-2 hours | Medium |
-| Phase 6: Cleanup | 15 min | Low |
-| Phase 7: Documentation | 1 hour | Low |
-| **Total** | **5-7 hours** | **Medium** |
-
----
-
-**End of Document**
diff --git a/docs/future-plan-to-remove-sites-site-builder-wrong-plan/SITES_REMOVAL_QUICK_REFERENCE.md b/docs/future-plan-to-remove-sites-site-builder-wrong-plan/SITES_REMOVAL_QUICK_REFERENCE.md
deleted file mode 100644
index 189889ba..00000000
--- a/docs/future-plan-to-remove-sites-site-builder-wrong-plan/SITES_REMOVAL_QUICK_REFERENCE.md
+++ /dev/null
@@ -1,329 +0,0 @@
-# Sites Container Removal - Quick Reference
-
-**Version:** 1.0
-**Date:** November 29, 2025
-
-> **Full Guide:** See [SITES_REMOVAL_GUIDE.md](./SITES_REMOVAL_GUIDE.md) for complete step-by-step instructions
-
----
-
-## TL;DR - What Changes
-
-### Current Architecture (3 Containers)
-```
-┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
-│ Frontend │ │ Sites │ │ Backend │
-│ Port: 8021 │ │ Port: 8024 │ │ Port: 8011 │
-│ │ │ - Site Builder │ │ │
-│ │ │ - Renderer │ │ │
-└─────────────────┘ └─────────────────┘ └─────────────────┘
-```
-
-### Target Architecture (2 Containers)
-```
-┌─────────────────┐ ┌─────────────────┐
-│ Frontend │ │ Backend │
-│ Port: 8021 │ │ Port: 8011 │
-│ - Main App │ │ │
-│ - Site Builder │ │ │
-│ - Renderer │ │ │
-└─────────────────┘ └─────────────────┘
-```
-
----
-
-## What Gets Removed
-
-❌ **Deleted:**
-- `/sites/` folder (after copying to frontend)
-- `/site-builder/` folder (empty, deprecated)
-- `/frontend/src/modules/siteBuilder/` (empty)
-- `igny8_sites` Docker container
-- Port 8024
-
-✅ **Kept:**
-- Backend `/api/v1/site-builder/` endpoints
-- Backend `/api/v1/publisher/` endpoints
-- Backend modules: `site_builder/`, `publisher/`
-- Backend business logic: `site_building/`, `publishing/`
-- Database tables (no changes)
-- `/data/app/sites-data/` directory
-
----
-
-## What Gets Moved
-
-### File Movements
-
-| From (Sites Container) | To (Frontend) |
-|------------------------|---------------|
-| `sites/src/builder/pages/wizard/` | `frontend/src/pages/Sites/Builder/Wizard.tsx` |
-| `sites/src/builder/pages/preview/` | `frontend/src/pages/Sites/Builder/Preview.tsx` |
-| `sites/src/builder/pages/dashboard/` | `frontend/src/pages/Sites/Builder/Dashboard.tsx` |
-| `sites/src/builder/components/layout/` | `frontend/src/components/sites/BuilderLayout.tsx` |
-| `sites/src/pages/SiteRenderer.tsx` | `frontend/src/pages/Sites/PublicSiteRenderer.tsx` |
-| `sites/src/loaders/loadSiteDefinition.ts` | `frontend/src/services/siteRenderer.api.ts` |
-| `sites/src/utils/layoutRenderer.tsx` | `frontend/src/utils/siteRenderer/layoutRenderer.tsx` |
-| `sites/src/utils/pageTypeRenderer.tsx` | `frontend/src/utils/siteRenderer/pageTypeRenderer.tsx` |
-| `sites/src/utils/templateEngine.tsx` | `frontend/src/utils/siteRenderer/templateEngine.tsx` |
-
----
-
-## Route Changes
-
-### Site Builder Routes
-
-| Old Route (Port 8024) | New Route (Port 8021) | Auth |
-|----------------------|----------------------|------|
-| `/builder` | `/sites/builder` | Required ✅ |
-| `/builder/preview` | `/sites/builder/preview` | Required ✅ |
-| `/builder/dashboard` | `/sites/builder/dashboard` | Required ✅ |
-
-### Sites Renderer Routes
-
-| Old Route (Port 8024) | New Route (Port 8021) | Auth |
-|----------------------|----------------------|------|
-| `/:siteSlug` | `/sites/view/:siteSlug` | None ❌ |
-| `/:siteSlug/:pageSlug` | `/sites/view/:siteSlug/:pageSlug` | None ❌ |
-
-**⚠️ Important:** Public site URLs will change! Update any hardcoded links.
-
----
-
-## Files to Update
-
-### Critical Files (Must Update)
-
-1. **`/frontend/src/App.tsx`**
- - Add site builder routes
- - Add public renderer routes
- - Add lazy imports
-
-2. **`/docker-compose.app.yml`**
- - Remove `igny8_sites` service
- - Add `/sites-data` volume mount to `igny8_frontend`
- - Add `SITES_DATA_PATH` env var to `igny8_frontend`
-
-3. **`/frontend/vite.config.ts`**
- - Add `SITES_DATA_PATH` environment variable
-
-### Optional Files (Verify/Update)
-
-4. **`/backend/igny8_core/settings.py`**
- - Verify CORS settings (remove port 8024)
-
-5. **`/frontend/src/components/sidebar/AppSidebar.tsx`**
- - Add site builder menu items
-
----
-
-## Critical Commands
-
-### 1. Backup First
-```bash
-cd /data/app/igny8
-tar -czf backup-sites-$(date +%Y%m%d-%H%M%S).tar.gz sites/ site-builder/
-cp docker-compose.app.yml docker-compose.app.yml.backup
-```
-
-### 2. Copy Files
-```bash
-# Create directories
-mkdir -p frontend/src/pages/Sites/Builder
-mkdir -p frontend/src/components/sites/builder
-mkdir -p frontend/src/utils/siteRenderer
-
-# Copy builder pages
-cp sites/src/builder/pages/wizard/WizardPage.tsx frontend/src/pages/Sites/Builder/Wizard.tsx
-cp sites/src/builder/pages/preview/PreviewCanvas.tsx frontend/src/pages/Sites/Builder/Preview.tsx
-cp sites/src/builder/pages/dashboard/SiteDashboard.tsx frontend/src/pages/Sites/Builder/Dashboard.tsx
-
-# Copy renderer
-cp sites/src/pages/SiteRenderer.tsx frontend/src/pages/Sites/PublicSiteRenderer.tsx
-cp sites/src/loaders/loadSiteDefinition.ts frontend/src/services/siteRenderer.api.ts
-
-# Copy utilities
-cp -r sites/src/utils/* frontend/src/utils/siteRenderer/
-```
-
-### 3. Rebuild & Restart
-```bash
-# Rebuild frontend
-cd /data/app/igny8/frontend
-docker build -t igny8-frontend-dev:latest -f Dockerfile.dev .
-
-# Stop sites container
-docker stop igny8_sites
-docker rm igny8_sites
-
-# Start updated frontend
-cd /data/app/igny8
-docker compose -f docker-compose.app.yml up -d igny8_frontend
-```
-
-### 4. Test
-```bash
-# Test site builder (requires auth)
-curl -I http://localhost:8021/sites/builder
-
-# Test public renderer
-curl -I http://localhost:8021/sites/view/test-site
-
-# Check logs
-docker logs -f igny8_frontend
-```
-
-### 5. Cleanup (After Verification)
-```bash
-cd /data/app/igny8
-rm -rf sites/
-rm -rf site-builder/
-rm -rf frontend/src/modules/siteBuilder/
-docker rmi igny8-sites-dev:latest
-```
-
----
-
-## Impact on Other Features
-
-### ✅ No Impact (These Still Work)
-
-| Feature | Why No Impact |
-|---------|---------------|
-| Planner module | Uses only backend API |
-| Writer module | Uses only backend API |
-| Linker module | Uses only backend API |
-| Optimizer module | Uses only backend API |
-| WordPress Publishing | Talks to backend, not affected |
-| Authentication | Frontend change only |
-| Billing/Credits | Backend only |
-| AI Content Generation | Backend/Celery only |
-
-### ⚠️ Needs Update (After Migration)
-
-| Feature | What to Update | Impact |
-|---------|----------------|--------|
-| Site Builder UI | Routes change to `/sites/builder/*` | Low - Internal only |
-| Public Site Links | URLs change to `/sites/view/{slug}` | Medium - External links |
-| Navigation Menu | Add site builder menu items | Low - UI only |
-| Tests | Update route tests if any | Low - Dev only |
-
----
-
-## Docker Compose Changes
-
-### Before (3 Services)
-```yaml
-services:
- igny8_frontend: # Port 8021
- igny8_sites: # Port 8024 ❌ REMOVE THIS
- igny8_backend: # Port 8011
- igny8_celery_worker:
- igny8_celery_beat:
-```
-
-### After (2 Services)
-```yaml
-services:
- igny8_frontend: # Port 8021 (updated)
- # igny8_sites removed
- igny8_backend: # Port 8011
- igny8_celery_worker:
- igny8_celery_beat:
-```
-
-### Frontend Service Update
-```yaml
-igny8_frontend:
- image: igny8-frontend-dev:latest
- container_name: igny8_frontend
- ports:
- - "0.0.0.0:8021:5173"
- environment:
- VITE_BACKEND_URL: "https://api.igny8.com/api"
- SITES_DATA_PATH: "/sites" # ← ADD THIS
- volumes:
- - /data/app/igny8/frontend:/app:rw
- - /data/app/sites-data:/sites:ro # ← ADD THIS
-```
-
----
-
-## Testing Checklist
-
-**Before Migration:**
-- [ ] Site builder wizard works at `http://localhost:8024/builder`
-- [ ] Site preview works at `http://localhost:8024/builder/preview`
-- [ ] Public site loads at `http://localhost:8024/{siteSlug}`
-
-**After Migration:**
-- [ ] Site builder wizard works at `http://localhost:8021/sites/builder`
-- [ ] Site preview works at `http://localhost:8021/sites/builder/preview`
-- [ ] Blueprint dashboard works at `http://localhost:8021/sites/builder/dashboard`
-- [ ] Public site loads at `http://localhost:8021/sites/view/{siteSlug}`
-- [ ] Auth required for builder routes
-- [ ] No auth required for public renderer
-- [ ] API calls succeed from frontend
-- [ ] No console errors in browser
-- [ ] Sites data loads from `/data/app/sites-data/`
-
----
-
-## Rollback (If Needed)
-
-```bash
-# Quick rollback
-cp docker-compose.app.yml.backup docker-compose.app.yml
-docker compose -f docker-compose.app.yml up -d igny8_sites
-
-# Full rollback
-cd /data/app/igny8
-tar -xzf backup-sites-YYYYMMDD-HHMMSS.tar.gz
-cd sites
-docker build -t igny8-sites-dev:latest -f Dockerfile.dev .
-docker compose -f docker-compose.app.yml up -d igny8_sites
-```
-
----
-
-## Estimation
-
-| Task | Time |
-|------|------|
-| Backup & Prep | 30 min |
-| Copy Files & Update Routes | 2 hours |
-| Docker Config Updates | 30 min |
-| Rebuild & Deploy | 30 min |
-| Testing | 1-2 hours |
-| Cleanup & Docs | 1 hour |
-| **Total** | **5-6 hours** |
-
----
-
-## Decision Matrix
-
-### Keep Separate Sites Container If:
-- ❌ You need different deployment schedules for sites vs main app
-- ❌ You want sites on different infrastructure
-- ❌ You have high traffic public sites (performance isolation)
-- ❌ You want to scale sites independently
-
-### Merge Into Frontend If:
-- ✅ You want simpler deployment (fewer containers)
-- ✅ You want unified routing and authentication
-- ✅ Sites are internal/low traffic
-- ✅ You want easier development (single app)
-- ✅ You want to reduce port complexity
-
----
-
-## Support
-
-**Full Documentation:** [SITES_REMOVAL_GUIDE.md](./SITES_REMOVAL_GUIDE.md)
-**Architecture Reference:** [MASTER_REFERENCE.md](./MASTER_REFERENCE.md)
-**API Reference:** [API-COMPLETE-REFERENCE.md](./API-COMPLETE-REFERENCE.md)
-
----
-
-**Last Updated:** November 29, 2025
-**Status:** Ready for implementation
diff --git a/docs/03-WORDPRESS-PLUGIN-API-INTEGRATION-GUIDE.md b/docs/wordpress-integration-and-other/03-WORDPRESS-PLUGIN-API-INTEGRATION-GUIDE.md
similarity index 100%
rename from docs/03-WORDPRESS-PLUGIN-API-INTEGRATION-GUIDE.md
rename to docs/wordpress-integration-and-other/03-WORDPRESS-PLUGIN-API-INTEGRATION-GUIDE.md
diff --git a/docs/04-WORDPRESS-BIDIRECTIONAL-SYNC-REFERENCE.md b/docs/wordpress-integration-and-other/04-WORDPRESS-BIDIRECTIONAL-SYNC-REFERENCE.md
similarity index 100%
rename from docs/04-WORDPRESS-BIDIRECTIONAL-SYNC-REFERENCE.md
rename to docs/wordpress-integration-and-other/04-WORDPRESS-BIDIRECTIONAL-SYNC-REFERENCE.md
diff --git a/docs/DEPLOYMENT-GUIDE-WP-FIXES.md b/docs/wordpress-integration-and-other/DEPLOYMENT-GUIDE-WP-FIXES.md
similarity index 100%
rename from docs/DEPLOYMENT-GUIDE-WP-FIXES.md
rename to docs/wordpress-integration-and-other/DEPLOYMENT-GUIDE-WP-FIXES.md
diff --git a/docs/WORDPRESS-INTEGRATION-FIXES-2025-11-30.md b/docs/wordpress-integration-and-other/WORDPRESS-INTEGRATION-FIXES-2025-11-30.md
similarity index 100%
rename from docs/WORDPRESS-INTEGRATION-FIXES-2025-11-30.md
rename to docs/wordpress-integration-and-other/WORDPRESS-INTEGRATION-FIXES-2025-11-30.md
diff --git a/docs/WORDPRESS-INTEGRATION-FIXES-IMPLEMENTATION-2025-12-01.md b/docs/wordpress-integration-and-other/WORDPRESS-INTEGRATION-FIXES-IMPLEMENTATION-2025-12-01.md
similarity index 100%
rename from docs/WORDPRESS-INTEGRATION-FIXES-IMPLEMENTATION-2025-12-01.md
rename to docs/wordpress-integration-and-other/WORDPRESS-INTEGRATION-FIXES-IMPLEMENTATION-2025-12-01.md
diff --git a/docs/WORDPRESS-INTEGRATION-REFACTOR-PLAN-2025-12-01.md b/docs/wordpress-integration-and-other/WORDPRESS-INTEGRATION-REFACTOR-PLAN-2025-12-01.md
similarity index 100%
rename from docs/WORDPRESS-INTEGRATION-REFACTOR-PLAN-2025-12-01.md
rename to docs/wordpress-integration-and-other/WORDPRESS-INTEGRATION-REFACTOR-PLAN-2025-12-01.md
diff --git a/docs/WORDPRESS-PUBLISHING-FIELD-MAPPING.md b/docs/wordpress-integration-and-other/WORDPRESS-PUBLISHING-FIELD-MAPPING.md
similarity index 100%
rename from docs/WORDPRESS-PUBLISHING-FIELD-MAPPING.md
rename to docs/wordpress-integration-and-other/WORDPRESS-PUBLISHING-FIELD-MAPPING.md
diff --git a/docs/WP-CONTENT-TEMPLATE-IMPLEMENTATION-PLAN.md b/docs/wordpress-integration-and-other/WP-CONTENT-TEMPLATE-IMPLEMENTATION-PLAN.md
similarity index 100%
rename from docs/WP-CONTENT-TEMPLATE-IMPLEMENTATION-PLAN.md
rename to docs/wordpress-integration-and-other/WP-CONTENT-TEMPLATE-IMPLEMENTATION-PLAN.md
diff --git a/docs/WP-PLUGIN-REFACTOR-PLAN.md b/docs/wordpress-integration-and-other/WP-PLUGIN-REFACTOR-PLAN.md
similarity index 100%
rename from docs/WP-PLUGIN-REFACTOR-PLAN.md
rename to docs/wordpress-integration-and-other/WP-PLUGIN-REFACTOR-PLAN.md
diff --git a/docs/WP-PUBLISHING-SIMPLE-REFERENCE.md b/docs/wordpress-integration-and-other/WP-PUBLISHING-SIMPLE-REFERENCE.md
similarity index 100%
rename from docs/WP-PUBLISHING-SIMPLE-REFERENCE.md
rename to docs/wordpress-integration-and-other/WP-PUBLISHING-SIMPLE-REFERENCE.md
diff --git a/docs/WP-REFACTOR-IMPLEMENTATION-SUMMARY.md b/docs/wordpress-integration-and-other/WP-REFACTOR-IMPLEMENTATION-SUMMARY.md
similarity index 100%
rename from docs/WP-REFACTOR-IMPLEMENTATION-SUMMARY.md
rename to docs/wordpress-integration-and-other/WP-REFACTOR-IMPLEMENTATION-SUMMARY.md