From dab294f18ae77b0c59a6f8940be9cfbba4016d30 Mon Sep 17 00:00:00 2001 From: michael Date: Mon, 12 Jan 2026 10:37:37 -0600 Subject: [PATCH] feat: streamline QC approval to skip translation pipeline QC approval now transitions jobs directly to pending_final_review since translation, TTS, and accessible video rendering happen before QC review. Removes unnecessary translate_and_synthesize_task trigger on approval. - Update approve_source() to use PENDING_FINAL_REVIEW status - Update bulk_approve_jobs() to use PENDING_FINAL_REVIEW status - Remove translate_and_synthesize_task.delay() calls from both endpoints - Update JobDetail progress indicator to reflect new flow - Update CLAUDE.md state machine documentation Co-Authored-By: Claude Opus 4.5 --- CLAUDE.md | 13 +++++++----- backend/app/api/v1/routes_jobs.py | 29 +++++++++----------------- frontend/src/routes/jobs/JobDetail.tsx | 10 +++++---- 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 6b3358a..969f4c9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -73,7 +73,9 @@ The development plan is the authoritative source for all implementation details. ## Job Status State Machine ``` -created → ingesting → ai_processing → pending_qc → approved_english | rejected → translating → tts_generating → pending_final_review → completed +created → ingesting → ai_processing → translating → tts_generating → rendering_video → pending_qc → pending_final_review → completed + ↓ + rejected ``` ## Key Architecture Decisions @@ -88,10 +90,11 @@ created → ingesting → ai_processing → pending_qc → approved_english | re ### Data Flow 1. Client uploads MP4 → GCS + MongoDB record 2. Celery worker processes video with Gemini 2.5 Pro -3. Generates English captions.vtt and audio_description.vtt -4. Reviewer QC approval triggers translation pipeline -5. Multi-language assets generated (translate/transcreate + TTS) -6. Final review and client notification with download links +3. Generates captions.vtt and audio_description.vtt for source language +4. Translation, TTS synthesis, and accessible video rendering run automatically +5. Job enters QC Review for reviewer approval (edits can trigger re-rendering) +6. QC approval moves job directly to Final Review +7. Final review and client notification with download links ### File Structure ``` diff --git a/backend/app/api/v1/routes_jobs.py b/backend/app/api/v1/routes_jobs.py index c2cf2ab..5f8e9e0 100644 --- a/backend/app/api/v1/routes_jobs.py +++ b/backend/app/api/v1/routes_jobs.py @@ -267,9 +267,9 @@ async def bulk_approve_jobs( errors.append(f"Job {job_id}: not in pending QC status") continue - # Determine the appropriate status based on source language - source_language = job_doc["source"].get("language", "en") - new_status = JobStatus.APPROVED_ENGLISH if source_language == "en" else JobStatus.APPROVED_SOURCE + # Transition directly to PENDING_FINAL_REVIEW + # Translation, TTS, and accessible video rendering now happen BEFORE QC + new_status = JobStatus.PENDING_FINAL_REVIEW # Build update operations update_set = { @@ -305,12 +305,8 @@ async def bulk_approve_jobs( if result: approved_count += 1 - # Trigger translation pipeline - try: - translate_and_synthesize_task.delay(job_id) - logger.info(f"Triggered translation task for bulk-approved job {job_id}") - except Exception as e: - logger.error(f"Failed to trigger translation task for job {job_id}: {e}") + # No need to trigger translate_and_synthesize_task - all processing done before QC + logger.info(f"Job {job_id} approved, transitioning directly to final review") else: errors.append(f"Job {job_id}: update failed (may have been modified concurrently)") @@ -591,9 +587,9 @@ async def approve_source( detail="Job not in pending QC status" ) - # Determine the appropriate status based on source language - source_language = job_doc["source"].get("language", "en") - new_status = JobStatus.APPROVED_ENGLISH if source_language == "en" else JobStatus.APPROVED_SOURCE + # Transition directly to PENDING_FINAL_REVIEW + # Translation, TTS, and accessible video rendering now happen BEFORE QC + new_status = JobStatus.PENDING_FINAL_REVIEW # Build update operations update_set = { @@ -635,13 +631,8 @@ async def approve_source( detail="Job not found or not in pending QC status" ) - # Trigger translation and synthesis pipeline immediately - try: - translate_and_synthesize_task.delay(job_id) - logger.info(f"Triggered translation task for approved job {job_id} (source: {source_language})") - except Exception as e: - logger.error(f"Failed to trigger translation task for job {job_id}: {e}") - # Don't fail the approval, just log the error + # No need to trigger translate_and_synthesize_task - all processing done before QC + logger.info(f"Job {job_id} approved, transitioning directly to final review") return JobResponse( id=str(result["_id"]), diff --git a/frontend/src/routes/jobs/JobDetail.tsx b/frontend/src/routes/jobs/JobDetail.tsx index 9a9942c..08d6c19 100644 --- a/frontend/src/routes/jobs/JobDetail.tsx +++ b/frontend/src/routes/jobs/JobDetail.tsx @@ -9,21 +9,23 @@ import { useToastContext } from '../../contexts/ToastContext'; const ProgressIndicator = ({ status }: { status: string }) => { + // New flow: processing happens before QC, approval goes directly to final review const steps = [ 'created', 'ingesting', 'ai_processing', - 'pending_qc', - 'approved', // Generic - matches both approved_english and approved_source 'translating', 'tts_generating', 'rendering_video', + 'pending_qc', 'pending_final_review', 'completed' ]; - // Map approved statuses to generic 'approved' for progress display - const normalizedStatus = (status === 'approved_english' || status === 'approved_source') ? 'approved' : status; + // Handle legacy approved_english/approved_source statuses (map to pending_final_review) + const normalizedStatus = (status === 'approved_english' || status === 'approved_source') + ? 'pending_final_review' + : status; const currentIndex = steps.indexOf(normalizedStatus); const isRejected = status === 'rejected'; const isFailed = status === 'tts_failed' || status === 'render_failed';