{
  "project_id": "03072026-003-Nguyen-Van-Troi",
  "project_name": "Nguyễn Văn Trỗi",
  "channel": "Vet Muc Thoi Gian",
  "workflow_version": "v1-19-step-history-video",
  "checklist_rule": "After completing any step, update this checklist JSON and the Markdown mirror immediately before reporting completion.",
  "current_step": 6,
  "created_at": "2026-07-03",
  "updated_at": "2026-07-03T10:17:01",
  "steps": [
    {
      "step": 1,
      "id": "receive_input_create_project",
      "name": "Receive story/input and create project folder",
      "status": "completed",
      "completed_at": "2026-07-03T10:17:01",
      "input": [
        "story_input",
        "main_character",
        "topic"
      ],
      "output": [
        "project_folder",
        "checklist_19_steps.json",
        "checklist_19_steps.md"
      ],
      "validation": [
        "Project folder exists",
        "Checklist JSON/MD exists"
      ],
      "notes": ""
    },
    {
      "step": 2,
      "id": "clean_story_split_scenes",
      "name": "Clean story and split scene/dense plan",
      "status": "completed",
      "completed_at": "2026-07-03T10:17:01",
      "input": [
        "script/source_story.txt"
      ],
      "output": [
        "script/cleaned_story.txt",
        "script/scenes.json",
        "script/scenes_validation.json"
      ],
      "validation": [
        "Cleaned story exists",
        "Scenes valid",
        "Metadata not turned into scenes"
      ],
      "notes": ""
    },
    {
      "step": 3,
      "id": "create_character_bible",
      "name": "Create character bible",
      "status": "completed",
      "completed_at": "2026-07-03T10:17:01",
      "input": [
        "script/cleaned_story.txt",
        "script/scenes.json"
      ],
      "output": [
        "script/character_bible.json"
      ],
      "validation": [
        "Character bible exists",
        "Main/supporting characters covered"
      ],
      "notes": ""
    },
    {
      "step": 4,
      "id": "approve_dense_plan",
      "name": "Create/validate/approve scenes dense plan",
      "status": "completed",
      "completed_at": "2026-07-03T10:17:01",
      "input": [
        "script/scenes.json",
        "script/character_bible.json"
      ],
      "output": [
        "script/scenes.json approved dense plan"
      ],
      "validation": [
        "Dense plan has scene_id/summary/narration/visual_prompt",
        "Approved for next step"
      ],
      "notes": ""
    },
    {
      "step": 5,
      "id": "generate_character_refs",
      "name": "Generate character references before scene images",
      "status": "completed",
      "completed_at": "2026-07-03T10:17:01",
      "input": [
        "script/scenes.json",
        "script/character_bible.json"
      ],
      "output": [
        "script/character_reference_plan.json",
        "characters/*_ref.png"
      ],
      "validation": [
        "Required refs generated before scene images",
        "Refs approved/recorded"
      ],
      "notes": ""
    },
    {
      "step": 6,
      "id": "generate_scene_images_thumbnails",
      "name": "Generate scene images and final thumbnails",
      "status": "completed",
      "completed_at": "2026-07-03T10:17:01",
      "input": [
        "approved character refs",
        "script/scenes.json"
      ],
      "output": [
        "images/scenes/scene_*.png",
        "output/thumbnails/thumb_16x9_final.png",
        "output/thumbnails/thumb_9x16_final.png"
      ],
      "validation": [
        "All scenes have 16:9 images",
        "Both thumbnails exist"
      ],
      "notes": ""
    },
    {
      "step": 7,
      "id": "generate_scene_tts",
      "name": "Generate TTS audio for each scene",
      "status": "pending",
      "completed_at": null,
      "input": [
        "script/scenes.json"
      ],
      "output": [
        "audio/scenes/scene_*.wav",
        "logs/step_07_tts_manifest.json"
      ],
      "validation": [
        "One TTS file per scene",
        "OmniVoice payload lowercased while subtitles/source keep original casing",
        "Manifest/log written"
      ],
      "notes": ""
    },
    {
      "step": 8,
      "id": "build_master_narration_timeline",
      "name": "Build master narration timeline on worker",
      "status": "pending",
      "completed_at": null,
      "input": [
        "audio/scenes/scene_*.wav",
        "script/scenes.json"
      ],
      "output": [
        "audio/master_narration.wav",
        "audio/master_narration_timeline.json"
      ],
      "validation": [
        "Master narration exists",
        "Timeline is source of truth"
      ],
      "notes": ""
    },
    {
      "step": 9,
      "id": "probe_real_audio_durations",
      "name": "Probe real audio durations on worker",
      "status": "pending",
      "completed_at": null,
      "input": [
        "audio/master_narration.wav"
      ],
      "output": [
        "audio/master_audio_probe.json"
      ],
      "validation": [
        "Worker probe duration locked"
      ],
      "notes": ""
    },
    {
      "step": 10,
      "id": "asr_master_word_timestamps",
      "name": "ASR master narration word timestamps",
      "status": "pending",
      "completed_at": null,
      "input": [
        "audio/master_narration.wav"
      ],
      "output": [
        "subtitles/master_narration_asr_words.json"
      ],
      "validation": [
        "ASR output has word timestamps"
      ],
      "notes": ""
    },
    {
      "step": 11,
      "id": "map_original_subtitles_to_asr",
      "name": "Map original narration to ASR word timing",
      "status": "pending",
      "completed_at": null,
      "input": [
        "script/scenes.json",
        "subtitles/master_narration_asr_words.json"
      ],
      "output": [
        "subtitles/master_subtitles.srt",
        "subtitles/master_subtitles_mapping.json"
      ],
      "validation": [
        "Subtitle text from original narration",
        "Heading scenes hard cue boundaries"
      ],
      "notes": ""
    },
    {
      "step": 12,
      "id": "clamp_subtitles_validate",
      "name": "Clamp subtitle safe gaps and validate no overlap",
      "status": "pending",
      "completed_at": null,
      "input": [
        "subtitles/master_subtitles.srt",
        "audio/master_audio_probe.json"
      ],
      "output": [
        "subtitles/master_subtitles_clamped.srt",
        "subtitles/master_subtitles_validation.json"
      ],
      "validation": [
        "Zero overlaps/invalid cues",
        "Within master duration"
      ],
      "notes": ""
    },
    {
      "step": 13,
      "id": "split_sync_safe_parts",
      "name": "Split render into sync-safe parts",
      "status": "pending",
      "completed_at": null,
      "input": [
        "audio/master_narration.wav",
        "subtitles/master_subtitles_clamped.srt"
      ],
      "output": [
        "parts/part_ranges.json",
        "parts/audio/part_XX.wav",
        "parts/subtitles/part_XX.srt"
      ],
      "validation": [
        "Part audio/subtitles rebased",
        "Part durations valid"
      ],
      "notes": ""
    },
    {
      "step": 14,
      "id": "render_parts_exact_audio_subtitle",
      "name": "Render each part with exact part audio/subtitle on worker",
      "status": "pending",
      "completed_at": null,
      "input": [
        "parts/part_ranges.json",
        "parts/audio/part_XX.wav",
        "parts/subtitles/part_XX.srt"
      ],
      "output": [
        "render_parts/part_XX.mp4",
        "render_parts/render_validation.json"
      ],
      "validation": [
        "All part MP4s valid",
        "Exact part audio/subtitle used",
        "Smooth/crossfade timing compensated"
      ],
      "notes": ""
    },
    {
      "step": 15,
      "id": "concat_rendered_parts",
      "name": "Concat rendered parts into main story video on worker",
      "status": "pending",
      "completed_at": null,
      "input": [
        "render_parts/part_XX.mp4",
        "render_parts/render_validation.json"
      ],
      "output": [
        "output/main_story.mp4",
        "output/main_story_probe.json",
        "output/concat_report.json"
      ],
      "validation": [
        "Part order matches part_ranges",
        "Main has audio/video",
        "Duration close to sum parts"
      ],
      "notes": ""
    },
    {
      "step": 16,
      "id": "qa_main_story",
      "name": "QA early/mid/late main story video",
      "status": "pending",
      "completed_at": null,
      "input": [
        "output/main_story.mp4",
        "output/concat_report.json"
      ],
      "output": [
        "output/main_story_qa_report.json"
      ],
      "validation": [
        "Early/mid/late and joins QA report written",
        "No blocker"
      ],
      "notes": ""
    },
    {
      "step": 17,
      "id": "create_project_intro",
      "name": "Create project intro with locked format",
      "status": "pending",
      "completed_at": null,
      "input": [
        "series/title metadata",
        "logo",
        "thumbnail",
        "voice refs"
      ],
      "output": [
        "output/intro/intro_audio.wav",
        "output/intro/intro.mp4",
        "output/intro/intro_probe.json"
      ],
      "validation": [
        "Locked intro form metadata respected",
        "TTS payload lowercase",
        "Intro audio/video valid"
      ],
      "notes": ""
    },
    {
      "step": 18,
      "id": "final_package_audio_safe",
      "name": "Final package intro + main + outro + BGM audio-safe",
      "status": "pending",
      "completed_at": null,
      "input": [
        "output/intro/intro.mp4",
        "output/main_story.mp4",
        "outro asset",
        "BGM asset"
      ],
      "output": [
        "output/final/final_video.mp4",
        "output/final/final_video_probe.json",
        "output/final/final_package_report.json"
      ],
      "validation": [
        "Audio-safe package on worker",
        "BGM volume default 0.20",
        "Probe/blackdetect report"
      ],
      "notes": ""
    },
    {
      "step": 19,
      "id": "final_qa_info_approve",
      "name": "QA final, write output/info.json, approve output",
      "status": "pending",
      "completed_at": null,
      "input": [
        "output/final/final_video.mp4",
        "thumbnails",
        "prior reports"
      ],
      "output": [
        "output/final/final_qa_report.json",
        "output/info.json"
      ],
      "validation": [
        "Final QA passed",
        "output/info.json complete",
        "Hashtags include #vetmucthoigian"
      ],
      "notes": ""
    }
  ]
}