# Handoff Report: Tier 5 Adversarial Coverage & Pipeline Hardening (Challenger M5-2)

**Agent**: `teamwork_preview_challenger` (Tier 5 Challenger 2 - Audio, Pipeline & Assembly)  
**Date**: 2026-10-08T08:28:00Z  
**Target Scope**: Features F8 through F13 (Audio Continuity Engine, Web Review Studio, Production Automation & Feature Assembly)  
**Test Suite Created**: `tests/test_tier5_pipeline_hardening.py` (20 adversarial tests)  
**Telemetry File**: `tests/adversarial_tier5_pipeline_hardening_results.json`

---

## 1. Observation

### Observation 1.1: `assemble_ep01_feature.py` Omission of Scene 15 (Cliffhanger)
- **File**: `05_Production_Pipeline/assemble_ep01_feature.py:18-35`
- **Code Quote**:
  ```python
  parts = [
      BASE_DIR / "04_Assets/videos/thap_ngu_nien_intro_complete_20s.mp4",
      BASE_DIR / "04_Assets/videos/prologue_hoai_niem_198x_to_gia_tinh_40s.mp4",
      BASE_DIR / "06_Exports/ep01_scene01_cinematic_master.mp4",
      BASE_DIR / "06_Exports/ep01_scene02_cinematic_master.mp4",
      ...
      BASE_DIR / "06_Exports/ep01_scene14_cinematic_master.mp4"
  ]
  ```
- **Finding**: Scene 15 (`BASE_DIR / "06_Exports/ep01_scene15_cinematic_master.mp4"` or versioned equivalent) is completely absent from `parts`.
- **Contract Reference**: `FilmMaker/INDEX_VA_DANH_MUC_CANH_QUAY.md:29` and `web_review/server.py:615` define Scene 15: `Cảnh 15: Gian thờ tổ tiên (Cliffhanger) - 6 shots (1m00s)` (`ep01_scene15_shot01` to `shot06`).
- **Verbatim Failure**:
  ```
  FAIL: test_f13_01_assemble_ep01_accounts_for_all_15_scenes (tests.test_tier5_pipeline_hardening.TestTier5PipelineHardening)
  AssertionError: 1 != 0 : assemble_ep01_feature.py misses scenes: ['scene15']. Scene 15 is the climax cliffhanger!
  ```

### Observation 1.2: `assemble_ep01_feature.py` Output Filename Lacks Mandatory Versioning
- **File**: `05_Production_Pipeline/assemble_ep01_feature.py:37`
- **Code Quote**:
  ```python
  output_master = EXPORTS_DIR / "thap_ngu_nien_ep01_grand_feature_master_10min.mp4"
  ```
- **Finding**: The output filename lacks the mandatory `_v<N>` versioning suffix required by user directive `2026-10-08T05:38:03Z` and `AGENTS.md` ("*Tất cả các file video MP4... BẮT BUỘC có hậu tố `_v<N>`... Master tập: `<ep_id>_grand_master_v1.mp4`*").
- **Verbatim Failure**:
  ```
  FAIL: test_f13_02_grand_feature_master_output_versioning (tests.test_tier5_pipeline_hardening.TestTier5PipelineHardening)
  AssertionError: False is not true : output_master 'thap_ngu_nien_ep01_grand_feature_master_10min.mp4' lacks mandatory _v<N> suffix (violates Directive 2026-10-08T05:38:03Z)
  ```

### Observation 1.3: `assemble_ep01_feature.py` Rigid Unversioned Scene Input Paths
- **File**: `05_Production_Pipeline/assemble_ep01_feature.py:21-34`
- **Finding**: The script hardcodes static filenames such as `ep01_scene01_cinematic_master.mp4`.
- **Contract Mismatch**: `05_Production_Pipeline/production_orchestrator.py:480` generates versioned masters using `resolve_versioned_path(EXPORTS_DIR, f"{scene_id}_cinematic_master")` which creates `ep01_scene01_cinematic_master_v1.mp4`. Because `assemble_ep01_feature.py` does not resolve versioned files (via `glob` or `_v*` fallback), it fails when orchestrated assets are generated.
- **Verbatim Failure**:
  ```
  FAIL: test_f13_03_scene_inputs_support_versioned_masters (tests.test_tier5_pipeline_hardening.TestTier5PipelineHardening)
  AssertionError: False is not true : assemble_ep01_feature.py must support versioned scene masters (_v1.mp4) produced by production_orchestrator.py
  ```

### Observation 1.4: `assemble_ep01_feature.py` Executes Top-Level `sys.exit(1)` on Import
- **File**: `05_Production_Pipeline/assemble_ep01_feature.py:40-44`
- **Code Quote**:
  ```python
  for i, p in enumerate(parts, 1):
      if not p.exists():
          print(f"[!] Lỗi: Thiếu thành phần #{i}: {p}")
          sys.exit(1)
  ```
- **Finding**: Lines 40-86 run at module top-level without an `if __name__ == "__main__":` guard. Attempting to import `assemble_ep01_feature` or test it programmatically terminates the Python process immediately.
- **Verbatim Failure**:
  ```
  FAIL: test_f13_04_no_top_level_side_effects_on_import (tests.test_tier5_pipeline_hardening.TestTier5PipelineHardening)
  AssertionError: False is not true : assemble_ep01_feature.py must be wrapped in `if __name__ == '__main__':` to allow programmatic invocation and testing
  ```

### Observation 1.5: `assemble_ep01_feature.py` Missing CLI Flag Support for Headless CI/CD
- **File**: `05_Production_Pipeline/assemble_ep01_feature.py`
- **Finding**: Lacks `argparse` or CLI options (`--dry-run`, `--check`, `--status`, `--version`). In headless CI/CD where render assets are mocked or incrementally produced, assembly cannot be validated without failing.
- **Verbatim Failure**:
  ```
  FAIL: test_f13_05_headless_cicd_dry_run_or_missing_parts_gracefulness (tests.test_tier5_pipeline_hardening.TestTier5PipelineHardening)
  AssertionError: False is not true : assemble_ep01_feature.py should provide argparse CLI support with --dry-run / --status options for headless CI/CD
  ```

### Observation 1.6: `assemble_ep01_feature.py` Stale Duration Specification Labels
- **File**: `05_Production_Pipeline/assemble_ep01_feature.py:37,75`
- **Code Quote**:
  ```python
  output_master = EXPORTS_DIR / "thap_ngu_nien_ep01_grand_feature_master_10min.mp4"
  ...
  print(f"🎬 Bắt đầu ghép nối 15 phân cảnh thành Grand Feature Master 7m30s...")
  ```
- **Finding**: Line 75 prints "7m30s" and line 37 hardcodes "10min", contradicting the EP01 expansion specification of 25-30 minutes (188 shots = 29m40s) from `ORIGINAL_REQUEST.md:12` and `PROJECT.md:30`.
- **Verbatim Failure**:
  ```
  FAIL: test_f13_06_duration_specification_consistency (tests.test_tier5_pipeline_hardening.TestTier5PipelineHardening)
  AssertionError: True is not false : assemble_ep01_feature.py contains stale duration labels (7m30s / 10min) that contradict 25-30m EP01 specification
  ```

### Observation 1.7: `audio_continuity_engine.py` Loudnorm Crash on Pure Silence in Two-Pass Mode
- **File**: `05_Production_Pipeline/audio_continuity_engine.py:438-450`
- **Code Quote**:
  ```python
  else:
      print("   [Pass 1 Fallback] File câm hoặc không đo được thông số, sử dụng single-pass loudnorm an toàn.")
  cmd = [
      self.ffmpeg, "-y",
      "-i", input_video,
      "-af", loudnorm_filter,
      "-c:v", "copy",
      ...
  ]
  ```
- **Finding**: When `measure_loudness` flags `is_silent=True` on a video with 0-amplitude audio, `normalize_loudness` falls back to `loudnorm=I=-14:TP=-1.0:LRA=9`. Applying FFmpeg `loudnorm` filter to pure silence causes mathematical NaN in normalization parameters, triggering AAC encoder failure: `[aac @ ...] Qavg: nan; 2 frames left in the queue on closing; Conversion failed!`.
- **Verbatim Failure**:
  ```
  FAIL: test_f10_two_pass_loudnorm_measurement_silence_guard (tests.test_tier5_pipeline_hardening.TestTier5PipelineHardening)
  AssertionError: False is not true : normalize_loudness on pure silence triggers FFmpeg AAC Qavg:nan crash in single-pass fallback
  ```

### Observation 1.8: Verified Passing Subsystems (13/20 Tests Passed)
- **F8 Mute Fallback & Stream Preconditioning**: Both Mode A (`boundary_smoothing`) and Mode B (`acrossfade`) properly synthesize stereo silence via `aevalsrc=0:d=...:s=48000:c=stereo` for silent inputs (`test_f08_mute_fallback_and_stream_preconditioning`: PASS).
- **F8 Active RMS Gain Staging**: Headroom clamping correctly caps gain adjustments so output max volume does not exceed -1.0 dBTP (`test_f08_gain_staging_headroom_clipping_protection`: PASS).
- **F9 4-Stem Mixer Resilience**: `mix_four_stems` operates smoothly when Stem 3 (Foley) or Stem 4 (Dialogue) are absent, applying notch filter and ducking only to available streams (`test_f09_four_stem_mixing_with_optional_stems`: PASS).
- **F11 Web Review Studio**: Default host `0.0.0.0` and port `1515` verified (`test_f11_01`: PASS); `/api/matrix/ep01` serves all 188 shots across 15 scenes (`test_f11_02`: PASS); concurrency 409 guard strictly blocks incoming `/api/generate` and `/api/concat` while busy (`test_f11_03`: PASS); input validation enforces required payload fields (`test_f11_04`: PASS); UTF-8 logging safely handles complex Vietnamese diacritics (`test_f11_05`: PASS).
- **F12 Orchestrator Integrity**: `get_shots_for_scene` indexes all 15 scenes including 6 shots in Scene 15 (`test_f12_01`: PASS); `resolve_versioned_path` increments `_v1`, `_v2`, `_v3` (`test_f12_02`: PASS); `find_rendered_video` prioritizes higher versions (`test_f12_03`: PASS); missing shots safely abort concat without throwing (`test_f12_04`: PASS); zero `cv2.VideoWriter` violations in concat routines (`test_f12_05`: PASS).

---

## 2. Logic Chain

1. **Premise 1 (Scene 15 Requirement)**: `ORIGINAL_REQUEST.md`, `PROJECT.md`, and `FilmMaker/INDEX_VA_DANH_MUC_CANH_QUAY.md` specify that EP01 contains 15 scenes totaling 188 shots (29m40s). Scene 15 is the dramatic cliffhanger ("Gian thờ tổ tiên - Cliffhanger").
2. **Step 2 (Omission in Script)**: Directly reading `assemble_ep01_feature.py:18-35` shows `parts` only lists scene 01 through scene 14. Scene 15 is entirely missing. Therefore, running `assemble_ep01_feature.py` produces an incomplete episode that cuts off before the cliffhanger.
3. **Premise 3 (Versioning Directive)**: User directive `2026-10-08T05:38:03Z` states that all video MP4 files MUST have a `_v<N>` version suffix.
4. **Step 4 (Assembly Output Violation)**: `assemble_ep01_feature.py:37` names the output `thap_ngu_nien_ep01_grand_feature_master_10min.mp4` without `_v<N>`. Furthermore, line 75 prints "7m30s" while line 37 says "10min", both violating the 25-30m expansion requirement.
5. **Premise 5 (Orchestrator Output Format)**: `production_orchestrator.py:master_scene_audio` uses `resolve_versioned_path(..., f"{scene_id}_cinematic_master")`, producing `ep01_sceneXX_cinematic_master_v1.mp4`.
6. **Step 6 (Input Incompatibility)**: `assemble_ep01_feature.py` hardcodes unversioned names (`ep01_sceneXX_cinematic_master.mp4`). When the orchestrator produces versioned scene masters, `assemble_ep01_feature.py` fails to find them.
7. **Step 7 (Import Side-Effects & CI/CD Fragility)**: Lines 40-44 in `assemble_ep01_feature.py` run on import without an `if __name__ == '__main__':` block. If any file is missing, it calls `sys.exit(1)`, crashing any test or pipeline importing it.
8. **Step 8 (Audio Engine Silence Defect)**: In `audio_continuity_engine.py:normalize_loudness`, when `meas["is_silent"]` is detected, the code falls back to `loudnorm_filter = f"loudnorm=I={target_lufs}:TP={target_tp}:LRA={target_lra}"`. Executing the `loudnorm` filter on pure silence produces NaN values that crash the AAC encoder with `[aac] Qavg: nan; Conversion failed!`.
9. **Conclusion**: Features F8 through F12 are fundamentally robust and adhere to contracts, but `assemble_ep01_feature.py` requires structural refactoring (scenes 1-15, versioning, CLI flags, main guard), and `audio_continuity_engine.py` requires an `anull` fallback for pure silence in `normalize_loudness`.

---

## 3. Caveats

1. **Physical Video Asset Availability**: In the development environment, not all 188 individual 10-second Muse.ai video clips are physically rendered yet (since video generation is an asynchronous human/AI browser process). Our tests synthesized deterministic test clips with exact video/audio stream properties using FFmpeg to test engine algorithms without needing 2 hours of GPU rendering.
2. **Web Server Port 1515**: Tests utilized FastAPI `TestClient(srv.app)` in-memory rather than binding to host port 1515 over the real network socket to avoid interfering with any active live review sessions on the development workstation.
3. **Review-Only Constraint Maintained**: Per agent instructions, the challenger did NOT mutate `assemble_ep01_feature.py` or `audio_continuity_engine.py`. Concrete, drop-in replacement solutions are provided below for Worker M5.

---

## 4. Conclusion & Actionable Recommendations for Worker M5

### Remediation Recipe 1: Overhaul `05_Production_Pipeline/assemble_ep01_feature.py`
Worker M5 should refactor `assemble_ep01_feature.py` with the following production-grade structure:
1. **Wrap in `def assemble_ep01(...)` and `if __name__ == "__main__":`**.
2. **Include Scene 15** in `parts` (`ep01_scene15_cinematic_master`).
3. **Dynamic Version Resolution for Scene Inputs**:
   ```python
   def resolve_scene_part(scene_id: str) -> Optional[Path]:
       # Search for highest version: ep01_sceneXX_cinematic_master_v*.mp4 or unversioned
       candidates = sorted(
           list(EXPORTS_DIR.glob(f"{scene_id}_cinematic_master*.mp4")) +
           list(EXPORTS_DIR.glob(f"{scene_id}_master*.mp4")),
           key=lambda p: p.stat().st_mtime,
           reverse=True
       )
       return candidates[0] if candidates else None
   ```
4. **Dynamic Versioned Output Filename**:
   Use `resolve_versioned_path(EXPORTS_DIR, "thap_ngu_nien_ep01_grand_feature_master")` producing `thap_ngu_nien_ep01_grand_feature_master_v1.mp4`.
5. **Add `argparse` CLI**:
   Support `--dry-run`, `--check`, `--output`, and `--allow-missing`. In `--dry-run` or `--check` mode, report missing/present scenes and exit code 0.
6. **Update Logs**:
   Update log output from "7m30s / 10min" to "25-30 phút (188 shots, 15 phân cảnh)".

### Remediation Recipe 2: Fix Pure Silence Guard in `05_Production_Pipeline/audio_continuity_engine.py`
In `audio_continuity_engine.py:normalize_loudness` (around line 438):
Replace:
```python
else:
    print("   [Pass 1 Fallback] File câm hoặc không đo được thông số, sử dụng single-pass loudnorm an toàn.")
```
With:
```python
elif meas and meas.get("is_silent"):
    print("   [Pass 1 Silence Guard] File câm (-inf), áp dụng bộ lọc anull an toàn để chống crash AAC encoder.")
    loudnorm_filter = "anull"
else:
    print("   [Pass 1 Fallback] Không đo được thông số, sử dụng single-pass loudnorm an toàn.")
```
When `meas.get("is_silent")` is True, bypass the `loudnorm` filter with `anull` to eliminate `Qavg: nan` crashes while preserving the audio stream structure.

---

## 5. Verification Method

To independently reproduce all empirical findings:

1. **Run the Tier 5 Hardening Test Suite**:
   ```powershell
   python tests/test_tier5_pipeline_hardening.py -v
   ```
   Or via pytest:
   ```powershell
   pytest tests/test_tier5_pipeline_hardening.py -v
   ```
   **Expected Result**: Exactly 13 tests PASS, 7 tests FAIL (documenting the 7 defects above).

2. **Inspect Telemetry File**:
   View `tests/adversarial_tier5_pipeline_hardening_results.json` to inspect the machine-readable summary of all 20 tests and 7 defect records.

3. **Verify Existing Tiers 1-4 Suite Unaffected**:
   ```powershell
   python tests/run_all_tests.py
   ```
   **Expected Result**: All 155 tests in Tiers 1-4 continue to pass 100%.

4. **Invalidation Condition**:
   Once Worker M5 applies Remediation Recipes 1 and 2, re-running `python tests/test_tier5_pipeline_hardening.py` will result in **20 passed, 0 failed (100% PASS)**.
