# Limited Pilot — Phase 1 Retry Fixture 설계 감사 (read-only)

작업 상태명: `LIMITED_PILOT_PHASE1_RETRY_FIXTURE_DESIGN_AUDIT_APPROVED_ACTIVE_FALSE`
완료 목표 상태명: `LIMITED_PILOT_PHASE1_RETRY_FIXTURE_DESIGN_AUDIT_READY_ACTIVE_FALSE`
작성: 2026-06-27 (KST) · 작성자: 아누 · 근거: main `189f1f0d` **코드 read-only 감사**
**raw key redacted. driver 실행 0 · fixture 생성 0 · flag 0.**

> ★ read-only 감사. retry 실행/ fixture 생성/ synthetic owner-proof 전부 미수행. ACTIVE=false 유지.

---

## 0. 가장 중요한 발견 — 1차 실패의 근본 원인은 "경로 불일치"
- **회장 성공 기준 verdict(`LIVE_PROCESSED` / `LIVE_PENDING_OWNER_PROOF`)는 `scan_live_inbox_once`(live inbox) 경로의
  verdict**다 (driver:2082-2178).
- 그런데 1차 Phase 1은 **event_strategy flag OFF** → driver.main이 `scan_once`(→ `process_one`) 경로로 갔다(driver:2354-2362).
  이 경로의 verdict 체계는 QUARANTINE / PROVENANCE_ADOPTED / CLOSEOUT_DONE / PICKUP_SKIP / FIRE_FAILED 이며,
  **schema gate(completion_signal 필수)**가 있어 fixture가 거기서 `schema_fail` quarantine됐다.
- ∴ 1차 실패는 fixture만의 문제가 아니라 **잘못된 경로 선택**이 더 근본이다. `LIVE_*` verdict를 보려면
  **event_strategy ON + fixture를 `p0b_live_inbox`에** 둬야 한다.

## 1. 두 경로 verdict 체계 (코드 근거)
**A) `scan_once` → `process_one` (event_strategy OFF, 1차 실행 경로)**
- schema gate(driver:1499-1515): `task_id`(non-empty str) + `completion_signal`(non-empty str) + path-traversal 안전. 미충족 → `schema_fail` quarantine.
- `collector_envelope`(driver:1518-1523): dict 아니면(부재) + provenance OFF → **`owner_unprovable` quarantine**.
- envelope 있으면 경로 A/B(contract_split, driver:1646-1713) → owner proof → PROVENANCE_ADOPTED / CLOSEOUT_DONE / owner_proof_fail.

**B) `scan_live_inbox_once` (event_strategy ON, 회장 성공 verdict 경로)**
- **schema 검증 없음** — `is_target`(final task-*.result.json)만(driver:2085). completion_signal 불필요.
- dedupe(seen) → `LIVE_SKIP_DEDUPE` / busy → `LIVE_PENDING_BUSY`
- **owner_gate_fn(p, executor_key="")**(driver:2123-2137):
  - gate_ready=**False** → **`LIVE_PENDING_OWNER_PROOF`** (fire 0, inbox 잔존, quarantine 아님)
  - gate_ready=**True** → callback_launch_fn 호출 → move 성공 → **`LIVE_PROCESSED`** / move 실패 → `LIVE_PENDING_MOVE`

## 2. 회장 보고 항목 (감사 답)
- **schema gate 필수 필드**: (process_one) `task_id`+`completion_signal`+path-safe. **(live_inbox) schema 검증 없음.**
- **completion_signal 최소 유효값**: non-empty `str`. **process_one 경로에만 필요, live_inbox 경로엔 불필요.**
- **collector_envelope 요구 여부**: (process_one) 부재 시 `owner_unprovable` quarantine. **(live_inbox) 무관** — owner_gate_fn만 본다.
- **owner-proof gate 진입 조건**: (live_inbox) is_target + not dedupe + not busy → `owner_gate_fn(p, executor_key="")` 호출.
- **owner_unprovable 발생 조건**: **process_one 경로** + collector_envelope 부재 + provenance_path OFF (driver:1523).
- **LIVE_PENDING_OWNER_PROOF 발생 조건**: **live_inbox 경로** + owner_gate **gate_ready=False**
  (= freshness FAIL[head_sha ≠ 로컬 canonical HEAD] / eligibility 미충족 / sealed ANU key 미준비 중 하나).
- **LIVE_PROCESSED 발생 조건**: live_inbox + gate_ready=True (freshness 통과[head_sha=canonical HEAD] + eligibility +
  sealed ANU key proof) + callback + processed move 성공.
- **callback_launch_verdict NOOP_DISABLED 관측 조건**: callback_launch_fn은 **gate_ready=True**일 때만 호출됨(driver:2141).
  즉 callback verdict는 **LIVE_PROCESSED 경로에서만** 관측 가능. `LIVE_PENDING_OWNER_PROOF`면 callback 미호출(관측 불가).
  callback flag OFF 시 내부 NOOP은 `callback_launch_audit.jsonl`에 기록(driver record는 BRIDGE_FIRED 라벨).

## 3. 위조 / 권한 경계 판단
- `owner_gate_fn`의 sealed key는 **driver(ANU)가 _default_sealed_key_loader로 로드** — fixture가 제공하지 않는다.
- fixture가 `owner_key_proof_present=true` 또는 envelope `self_key_used=true`를 claim → **self-key 위반**
  (process_one: `QREASON_OWNER_PICKUP_SELF_KEY_CLAIM` quarantine / live_inbox: owner_gate가 거부). = 위조 경계.
- fixture가 self/owner-key를 claim하지 않고 freshness+eligibility만 충족 → gate가 **driver의 정당한 sealed ANU key로
  proof**(위조 아님). 그러나 이는 owner-proof "통과"(LIVE_PROCESSED)이므로 **회장 정책상 별도 승인 영역**.

## 4. ★ 추천 retry 목표 verdict = `LIVE_PENDING_OWNER_PROOF` (안전 차단, 위조 0)
- 경로: **event_strategy ON + fixture를 `memory/events/p0b_live_inbox/task-<id>.result.json`에**.
- fixture: self/owner-key claim **0**. **head_sha를 canonical HEAD(189f1f0d)와 의도적으로 불일치**(freshness FAIL)
  → owner_gate gate_ready=False → `LIVE_PENDING_OWNER_PROOF`. fire 0, inbox 잔존, quarantine 아님, 위조 0.
- 이로써 **owner-proof 계층까지 도달**(schema_fail 극복) + **owner-proof는 통과 안 함**(안전) 둘 다 충족.
- `owner_unprovable`(process_one 경로)은 대안이나, 회장 성공 기준 verbatim(`LIVE_*`)과 정렬되는 건 live_inbox의
  `LIVE_PENDING_OWNER_PROOF`다 → 이것을 1순위 추천.

## 5. ★ retry 실행 승인 전 남은 결정 (회장)
1. **event_strategy flag ON 허용 여부** — 1차와 달리 retry는 `p0b_event_strategy_enabled`=enabled가 **추가로 필요**
   (live_inbox 경로 진입 조건). ON/OFF 절차·종료 복귀에 이 flag 1개가 추가된다.
2. **live_inbox 경로 사용 확정** (fixture를 p0b_inbox가 아니라 p0b_live_inbox에).
3. **retry 목표 verdict = `LIVE_PENDING_OWNER_PROOF` 확정** (LIVE_PROCESSED는 별도 승인 유지).
4. fixture freshness 의도적 불일치(head_sha ≠ canonical) 방식 승인.
5. retry도 surface-only(callback flag OFF · real_launch_fn 미주입 · systemd 미사용 · 1회 · OFF 복귀 · closeout archive) 유지.

## 6. 안전 불변 (이 감사 중)
- driver 실행 0 · fixture 생성 0 · flag 0 · real fire 0. ACTIVE=false · 코드 read-only.
- quarantine 파일 복원 0 · archive 28건 이동 0.
