# task-2729+8 — P0-B real wake 결선 (WAKE_BUILT argv 실 실행) audit-first hardening

## 레벨
Lv.3 (시스템 hardening 구현 + isolated 검증 — production ACTIVE 전환 아님)

## 한 줄 목표
driver가 `WAKE_BUILT` 반환 시 surface 만 하던 wake argv(`cokacdir --cron …`)를 **안전하게 실 실행**하는 결선을 설계·구현하되, **real ANU spawn 실행은 dispatch 전 0 / mock launcher decision-only 로 readiness 만 검증**. **canonical 무오염 · production ACTIVE=false 고정 · systemctl enable 0 · raw key 0.** "systemd enable 전에 real wake 결선이 안전하게 가능한지"를 audit-first 로 확정.

## 현재 미결선 지점 (단일 소스, merged main e386d4cf)
- wake argv 생성: `pickup_once` → `anu_runner_pickup_and_fire` (`dispatch/anu_owned_callback_enforcement.py`). argv = `cokacdir --cron … --key <ANU_KEY>` (sealed key 런타임 로드, 비-ANU key → argv=None fail-closed).
- **실행 미결선**: `dispatch/anu_pickup_driver.py` `process_one` WAKE_BUILT 분기(538–547줄) — `# ★ driver 는 argv 를 실행하지 않음 (P0-a dry_run, 실제 wake 0)`, `fire_cron_id=None`. driver 가 `res.argv` 를 **읽지도 실행하지도 않음**.

## 설계 (구현 가능 범위)
### W1. 신규 wake launcher 모듈 (`dispatch/anu_pickup_wake_launcher.py`)
- 단일 책임: WAKE_BUILT argv(이미 sealed key 포함)를 **권한 경로로 실 실행**(cokacdir cron 발사). driver/runner 는 decision-only 유지(관심사 분리).
- `dry_run=True`(기본) → **실행 0, 호출 기록만**(audit-neutral, production ledger write 0). `dry_run=False` + production → subprocess 실 실행.
- **raw key 0**: argv 를 stdout/audit/log 에 **미출력**(redaction). subprocess args 로만 전달.
- **dedupe**: launch 전 ledger `(task_id, sha256)` 확인 → 중복 wake 0.
- **audit**: launch 결과 jsonl 기록(key literal 0).
- **fail-closed**: argv None / 비-ANU key / ledger 확인 실패 → wake 금지(launch 0).
### W2. driver launcher_fn 주입 결선 (`dispatch/anu_pickup_driver.py`)
- `process_one`/`scan_once` 에 `launcher_fn=None`(기본=실행 0, **현행 동작 보존**) 주입. WAKE_BUILT 분기에서 `launcher_fn` 주어지면 `launcher_fn(res.argv, …)` 호출 → real wake. 미주입 시 현행(surface only).
- ledger/marker failure(LEDGER_WRITE_FAILED) / legacy skip / MAX_FILES defer / terminal SKIP → WAKE_BUILT 미도달 → launcher 미호출.

## 필수 확인 (회장 verbatim 10 — 검증 항목)
1. wake argv 생성 위치(pickup_once WAKE_BUILT) + 실행 미결선 위치(driver 538–547) 명시.
2. real spawn 실행 책임 = **신규 launcher 모듈**(driver=decision-only, launcher=실행).
3. duplicate wake 방지: pickup_once ledger dedupe + launcher launch-전 dedupe 재확인.
4. terminal marker no-op: SKIP_TERMINAL → WAKE_BUILT 아님 → launcher 미호출.
5. MAX_FILES/legacy cutoff와 real wake 순서: legacy skip·MAX defer → WAKE_BUILT 아님 → wake 0. post-epoch + 6조건 통과 + WAKE_BUILT → launcher.
6. ledger/marker failure 시 wake 금지: LEDGER_WRITE_FAILED → wake 0.
7. raw key exposure 0: launcher argv/key 미출력(redaction), subprocess args 만.
8. runaway guard: flag DISABLED 기본 + flock + MAX_FILES + dedupe + launcher dry_run 기본.
9. dry-run 이 production ledger 에 POSTED/DEDUPED 미기록(OWNER_TRIGGER_DRY_RUN_LEDGER_CONTAMINATION 교훈 — dry-run isolated/audit-neutral).
10. mock launcher 로 decision-only 검증 가능: `launcher_fn=mock` → 실행 0, 호출 인자 기록만 → readiness 확정.

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "dispatch/anu_pickup_wake_launcher.py"
    - "dispatch/anu_pickup_driver.py"
    - "tests/regression/test_anu_pickup_real_wake_wiring_2729p8.py"
    - "memory/reports/task-2729+8.md"
    - "memory/plans/p0b-pickup/real_wake_wiring_design_260606.md"
    - "memory/events/task-2729+8.*"
    - "memory/tasks/task-2729+8-real-wake-wiring.md"
  read_only_reference:
    - "dispatch/anu_result_pickup_runner.py (★ pickup_once WAKE_BUILT argv — read only)"
    - "dispatch/anu_owned_callback_enforcement.py (★ anu_runner_pickup_and_fire argv 빌드 — read only)"
    - "tests/regression/test_anu_pickup_driver_2721.py (무영향 확인)"
    - "tests/regression/test_anu_pickup_activation_hardening_2729p7.py (무영향 확인)"
    - "scripts/anu_pickup_entrypoint.sh (read only)"
    - "memory/plans/p0b-pickup/activation_approval_packet_260606.md (입력)"
  forbidden_paths:
    - "dispatch/anu_result_pickup_runner.py"
    - "dispatch/anu_owned_callback_enforcement.py"
    - "scripts/anu_pickup_entrypoint.sh"
    - "deploy/systemd/**"
    - "memory/events/task-*.result.json"
    - "memory/events/owner-trigger-audit.jsonl"
    - "memory/events/callback_4tuple_index.jsonl"
    - "memory/state/**"
    - "memory/p0b_state/**"
    - "utils/**"
    - "scripts/finish-task.sh"
    - "dispatch.py"
    - ".github/**"
    - "hooks/**"
    - "/home/jay/.claude/**"
    - "/home/jay/.config/systemd/**"
    - "/usr/local/bin/cokacdir"
```

## EXPECTED FILES (정확히 5 — 초과 시 중단·HOLD_FOR_CHAIR)
1. `dispatch/anu_pickup_wake_launcher.py` — 신규 launcher(W1)
2. `dispatch/anu_pickup_driver.py` — launcher_fn 주입 결선(W2, default None=현행 보존)
3. `tests/regression/test_anu_pickup_real_wake_wiring_2729p8.py` — 회귀 + mock launcher decision-only
4. `memory/reports/task-2729+8.md` — audit/구현 결과
5. `memory/plans/p0b-pickup/real_wake_wiring_design_260606.md` — pilot design
- (runner/callback_enforcement 수정 0 — argv 빌드 기존 재사용. 기존 회귀 무영향 확인만)

## LOCK / 금지 (회장 verbatim)
1. systemctl enable --now  2. production ACTIVE 전환  3. activation_epoch canonical write  4. canonical result.json 이동·삭제·quarantine  5. **real ANU spawn 실행(dispatch 검증 단계)**  6. 실제 PR merge/push/comment  7. raw ANU key 출력  8. ACTIVE=true 선언  9. legacy result.json 재처리
- 모든 audit/dry-run/pilot **isolated temp root** 강제 · canonical 무오염 · dry-run production ledger 무기록
- driver launcher_fn **default None**(현행 보존) — production launcher 결선은 본 task 아님(activation 별도)

## ★ 회장 verbatim 필수 검증 (12)
1. WAKE_BUILT 에서만 launcher 호출. 2. legacy cutoff 대상 launcher 0. 3. terminal marker 존재 시 launcher 0. 4. MAX_FILES 초과 defer 시 launcher 0. 5. ledger/marker failure 시 launcher 0 또는 fail-safe. 6. duplicate wake 0. 7. raw ANU key 출력 0. 8. subprocess/os.system 등 실제 spawn 0. 9. dry-run/mock 은 isolated temp root 에서만. 10. canonical ledger/events/state 영향 0. 11. ACTIVE=false 유지. 12. 기존 decision-only 동작 보존(launcher_fn=None 기본).

## ★ 회장 verbatim 중단 조건 (8 — 하나라도 시 즉시 HOLD_FOR_CHAIR)
1. expected_files 5파일 초과. 2. real spawn 없이는 검증 불가. 3. canonical write 필요. 4. raw key 노출 위험. 5. duplicate wake 방지 불명확. 6. ACTIVE=true 필요. 7. systemd enable 필요. 8. fresh HIGH/CRITICAL 발생.

## 완료 판정 (회장 verbatim)
- **`REAL_WAKE_READINESS_VERIFIED_ACTIVE_FALSE`** 또는 **`HOLD_FOR_CHAIR`**.
- ★ 본 task PASS 여도 **production ACTIVE 전환 아님 / real wake 실행 0**. pickup chain = IMPLEMENTED / WIRED candidate / ACTIVE=false 유지. PASS = "real wake 결선 readiness" 입력 자료. systemd enable·activation_epoch 생성·real wake pilot·production activation 은 모두 별도 회장 승인 전까지 금지.

## doctrine
직접 코딩 금지(ANU)/봇 위임 / same-PR post-Gemini push 금지 / chain hard limit / long polling 금지 / cron PROMPT ≤2800자·≤3900 bytes / callback ANU key 독립 발사·self-collector 금지 / OWNER_TRIGGER_DRY_RUN_LEDGER_CONTAMINATION 재발 방지.
