# HANDOFF REPORT: Milestone M1 Iteration 2 (Prompts & Character Safeguards Remediation Analysis)

**Agent ID**: `explorer_m1_remediation_2`  
**Role**: Explorer & Remediation Architect  
**Milestone**: M1 Iteration 2 (Prompts & Character Safeguards Remediation)  
**Workspace**: `c:\Projects\KieuStory`  
**Timestamp**: 2026-10-09T04:35:00Z  
**Type**: Hard Handoff  

---

## 1. Observation

### 1.1 Direct Code & File Observations on Scene 10 Inversion
1. In `episodes/ep01/screenplay.md` (lines 1350-1445):
   - `ep01_scene10_shot03`: "Kiều qua rào sang thư phòng (Tracking Shot Kiều Night Stroll)" -> Visual: Kiều's light footsteps, green silk robe in the moonlight.
   - `ep01_scene10_shot06`: "Kiều giãi bày tấc lòng son (Close-Up Kiều Devotion)" -> Visual: Close-up Thúy Kiều gazing firmly into Kim Trọng's eyes; Dialogue On-screen: Thúy Kiều.
   - `ep01_scene10_shot11`: "Kiều ôm đàn tỳ bà so dây dưới trăng (Medium Shot Kiều with Pipa)" -> Visual: Kiều embraces the antique Pipa lute, tuning strings under the moonlight.
   - `ep01_scene10_shot12`: "Tiếng đàn tỳ bà réo rắt khúc tương tư (Close-Up Pipa Performance)" -> Visual: Kiều's slender fingers dancing across the lute frets; musical solo climax of Episode 1.
2. In `episodes/ep01/prompts/muse_prompts.json` and `02_AI_Prompts/muse_ai_video_prompts.json`:
   - Verbatim check on disk:
     - `ep01_scene10_shot03`: `"character_asset_ref": "04_Assets/characters/01_Main_Protagonists/kim_trong_18yo_720p.png"`
     - `ep01_scene10_shot06`: `"character_asset_ref": "04_Assets/characters/01_Main_Protagonists/kim_trong_18yo_720p.png"`
     - `ep01_scene10_shot11`: `"character_asset_ref": "04_Assets/characters/01_Main_Protagonists/kim_trong_18yo_720p.png"`
     - `ep01_scene10_shot12`: `"character_asset_ref": "04_Assets/characters/01_Main_Protagonists/kim_trong_18yo_720p.png"`
   - Git diff confirms: Worker 1 in Iteration 1 performed an indiscriminate range replacement from `ep01_scene10_shot03` through `ep01_scene10_shot12`, overwriting all shots with `kim_trong_18yo_720p.png`.

### 1.2 Direct Observations on Scene 06 & Scene 05 Asset Leaks
1. In `episodes/ep01/prompts/muse_prompts.json`:
   - All 14 shots of Scene 06 (`ep01_scene06_shot01` to `shot14`) have `"character_asset_ref": null` (missing).
   - In `02_AI_Prompts/gemini_banana_prompts.json`:
     - `ep01_scene06_shot04` (Close-up Kim Trọng): `"character_anchor": "vuong_quan"`
     - `ep01_scene06_shot06` (Kim Trọng dismounting): `"character_anchor": "thuy_kieu_maiden + thuy_van"`
     - `ep01_scene06_shot10` (Close-up Kim Trọng thunderstruck): `"character_anchor": "thuy_kieu_maiden + thuy_van"`
     - `ep01_scene06_shot12` (Kim Trọng bowing): `"character_anchor": "thuy_kieu_maiden + vuong_quan + thuy_van"`
   - Empirical execution of `po.resolve_start_frame_v2`:
     - `ep01_scene06_shot04` -> `vuong_quan_16yo_720p.png` (Mismatch)
     - `ep01_scene06_shot06` -> `thuy_kieu_maiden_16yo_720p.png` (Leak)
     - `ep01_scene06_shot10` -> `thuy_kieu_maiden_16yo_720p.png` (Leak)
     - `ep01_scene06_shot12` -> `thuy_kieu_maiden_16yo_720p.png` (Leak)
2. In Scene 05:
   - In `screenplay.md` (lines 819-915):
     - `ep01_scene05_shot13`: "Trung cận Vương Quan (MCU - Anti-Male-Tears Directive R4)"
     - `ep01_scene05_shot16`: "Trung cảnh Vương Quan thuật chuyện Đạm Tiên" (Vương Quan on-screen monologue)
     - `ep01_scene05_shot24`: "Trung cận Vương Quan can ngăn" (Vương Quan on-screen dialogue)
   - In `muse_prompts.json`: `character_asset_ref` is `null` for all three shots.
   - In `02_AI_Prompts/gemini_banana_prompts.json`:
     - `ep01_scene05_shot13`: `"character_anchor": "thuy_van"`
     - `ep01_scene05_shot16`: `"character_anchor": "thuy_kieu_maiden"`
     - `ep01_scene05_shot24`: `"character_anchor": "thuy_kieu_maiden"`
   - Empirical execution: `ep01_scene05_shot16` and `shot24` resolve to `thuy_kieu_maiden_16yo_720p.png`.

### 1.3 Direct Observations on `production_orchestrator.py` Unilateral Guard
In `05_Production_Pipeline/production_orchestrator.py` lines 320-378:
- Line 320: `is_kim_trong = "kim_trong" in curr_anchor and "thuy_kieu" not in curr_anchor`
- Line 327: `if is_kim_trong and "thuy_kieu" in str(asset_ref).lower(): asset_ref = "kim_trong_18yo_720p.png"`
- Line 375: `if is_kim_trong and resolved_path and "thuy_kieu" in resolved_path.lower(): resolved_path = ...`
- There is **no variable or logic** for `is_thuy_kieu`, `is_vuong_quan`, `is_vuong_ong`, or `is_thuy_van`.
- When `curr_anchor` is `thuy_kieu_maiden` and `asset_ref` is `kim_trong_18yo_720p.png`, Step A accepts `kim_trong` directly without override, and Step D does not execute.

### 1.4 Direct Observations on `tests/test_critic_gate.py` Test Harness Bypass
In `tests/test_critic_gate.py` lines 362, 385, 394:
- Line 362: `resolved = po.resolve_start_frame("ep01_scene02_shot08", {})`
- Line 385: `resolved = po.resolve_start_frame("ep01_scene09_shot04", {})`
- Line 394: `resolved = po.resolve_start_frame(sid, {})`
- Because `{}` is passed, `shot_data.get("character_asset_ref")` evaluates to `None`, bypassing Step A entirely and masking the defective prompt registries.

---

## 2. Logic Chain

1. **Chain from Observation 1.1 to Defect 1 (Scene 10 Inversion)**:
   - Observation 1.1 proves that shots 03, 06, 11, 12 in `screenplay.md` are centered on Thúy Kiều.
   - Observation 1.1 proves that `muse_prompts.json` assigns `kim_trong_18yo_720p.png` to all of them.
   - Observation 1.3 proves that `resolve_start_frame()` does not protect Thúy Kiều from Kim Trọng.
   - Conclusion: When rendered, Muse.ai will receive Kim Trọng's male scholar portrait as the input Start Frame while the motion prompt instructs "Kiều gảy đàn tỳ bà", causing cross-gender character mutation at the climax of Episode 1.

2. **Chain from Observation 1.2 to Defect 2 (Scene 06 & Scene 05 Leaks)**:
   - In Scene 06, because `character_asset_ref` is `None`, `resolve_start_frame()` falls back to `curr_anchor = get_character_anchor()`.
   - `gemini_banana_prompts.json` contains scrambled anchors mapping shots 04, 06, 10, 12 to `vuong_quan` and `thuy_kieu_maiden`.
   - In Scene 05, shots 16 and 24 lack `character_asset_ref` and have banana anchors set to `thuy_kieu_maiden`.
   - Conclusion: Both male leads (Kim Trọng in Scene 06 and Vương Quan in Scene 05) leak Thúy Kiều's portrait as Start Frame.

3. **Chain from Observation 1.3 to Defect 3 (Safeguard Gap)**:
   - The current safeguard in `production_orchestrator.py` is asymmetrical.
   - To achieve complete defense-in-depth, safeguards must be bilateral and multi-character:
     - `is_kim_trong` rejects `thuy_kieu`
     - `is_thuy_kieu` rejects `kim_trong`
     - `is_vuong_quan` rejects `thuy_kieu`
     - `is_vuong_ong` rejects `thuy_kieu`
     - `is_thuy_van` rejects `thuy_kieu`
   - This must be enforced in Step A (`asset_ref`), Step C (`reference_start_frame`), and Step D (`resolved_path`).

4. **Chain from Observation 1.4 to Defect 4 (Test Hardening)**:
   - Passing `{}` strips all prompt data.
   - Replacing `{}` with `all_shots.get(sid, {})` from `po.get_all_shots()` ensures tests execute against actual production configuration.
   - Adding adversarial test cases where `character_asset_ref` is intentionally inverted proves the safeguards hold under corrupted inputs.

---

## 3. Caveats

- **Scope Boundary**: This investigation is strictly read-only and analytical. No production code, prompts, or test files were mutated during this exploration. Complete recipes and diffs are documented in `remediation_prompts_safeguards.md`.
- **Challenger 2 Probe Assertion Note**: `tests/test_m1_challenger2_probe.py` currently asserts the existence of anomalies (`assert len(defects) == 2` and `assert "ep01_scene06_shot06" in anomaly_shot_ids`). When the implementer repairs the defects, those probe assertions will naturally fail until updated to assert 0 defects.
- No other caveats.

---

## 4. Conclusion

The root causes of all 4 defects are fully diagnosed with complete evidence chains. A comprehensive remediation blueprint has been delivered in:
`c:\Projects\KieuStory\.agents\teamwork\explorer_m1_remediation_2\remediation_prompts_safeguards.md`

### Summary of Required Actions for Implementer:
1. **Scene 10 Prompts**: Revert `character_asset_ref` in `ep01/prompts/muse_prompts.json` and `02_AI_Prompts/muse_ai_video_prompts.json` to `thuy_kieu_maiden_16yo_720p.png` for shots 03, 06, 09, 11, 12; retain `kim_trong_18yo_720p.png` for shots 04, 05, 07, 08, 10, 13.
2. **Scene 06 Prompts**: Populate explicit `character_asset_ref` for all 14 shots in `muse_prompts.json` (Kim Trọng on 03, 04, 06, 10, 12, 14; Tiểu Đồng on 05; Vương Quan on 07; Thúy Kiều on 08, 09, 11, 13) and harmonize `gemini_banana_prompts.json`.
3. **Scene 05 Prompts**: Set `character_asset_ref` to `vuong_quan_16yo_720p.png` and `character_anchor` to `vuong_quan` for shots 13, 16, 24.
4. **Bilateral Safeguard**: Implement multi-character reciprocal overrides in `05_Production_Pipeline/production_orchestrator.py`.
5. **Hardened Critic Gate Tests**: Replace empty `{}` calls with live data from `po.get_all_shots()` in `tests/test_critic_gate.py` and verify all Scene 05, 06, 10 authentic resolutions.

---

## 5. Verification Method

To independently verify the diagnosis and validate the proposed remediation:

```powershell
# 1. Reproduce Scene 10 Inversion on Thúy Kiều Pipa shots (Observed: returns kim_trong):
python -c "
import sys
sys.path.insert(0, '05_Production_Pipeline')
import production_orchestrator as po
all_shots = po.get_all_shots()
for sid in ['ep01_scene10_shot03', 'ep01_scene10_shot06', 'ep01_scene10_shot11', 'ep01_scene10_shot12']:
    print(sid, '->', po.resolve_start_frame(sid, all_shots.get(sid, {})))
"

# 2. Reproduce Scene 06 Kim Trọng leaking Thúy Kiều & Vương Quan:
python -c "
import sys
sys.path.insert(0, '05_Production_Pipeline')
import production_orchestrator as po
all_shots = po.get_all_shots()
for sid in ['ep01_scene06_shot04', 'ep01_scene06_shot06', 'ep01_scene06_shot10', 'ep01_scene06_shot12']:
    print(sid, '->', po.resolve_start_frame(sid, all_shots.get(sid, {})))
"

# 3. Reproduce Scene 05 Vương Quan leaking Thúy Kiều:
python -c "
import sys
sys.path.insert(0, '05_Production_Pipeline')
import production_orchestrator as po
all_shots = po.get_all_shots()
for sid in ['ep01_scene05_shot16', 'ep01_scene05_shot24']:
    print(sid, '->', po.resolve_start_frame(sid, all_shots.get(sid, {})))
"
```

**Invalidation Conditions**:
- If `ep01_scene10_shot11` with live prompt data resolves to `thuy_kieu_maiden_16yo_720p.png` and NOT `kim_trong`.
- If `ep01_scene06_shot06` with live prompt data resolves to `kim_trong_18yo_720p.png` and NOT `thuy_kieu`.
- If `ep01_scene05_shot16` with live prompt data resolves to `vuong_quan_16yo_720p.png` and NOT `thuy_kieu`.
