# P0-b OS-level callback wake driver — 최소 설계안 (2026-06-01)

> 상태: **설계안만**. dispatch/구현/설치 0. 회장 승인 전까지 진행 금지(후속 2).
> 목표(후속 3): result.json 자동 감지 → `pickup_once` 호출 → ANU key wake → 독립 세션 spawn 까지의 **실제 production path 결선**.
> 전제: P0-a merge 완료(main 29175f80). pickup_once = 락-free·idempotent(dedupe 4-tuple + terminal done-marker + no-op). active 는 P0-b 5단계 증거 후에만.

## 1. driver 방식 후보 (3안)
- **A안 systemd path unit (권장)**: `anu-pickup.path`(PathModified/DirectoryNotEmpty on memory/events) → `anu-pickup.service`(Type=oneshot, runner 1회 실행). 이벤트 구동(near-instant)·journald 로깅·Restart 정책·disable 1줄. 단 user/system unit 설치 필요(lingering).
- **B안 crontab poll runner (최소)**: `* * * * *` runner 가 신규 result.json 스캔→pickup. 데몬 0·재부팅 견고·구현 최소. 단 최대 ~60s 지연(P0-b 는 sub-second 불필요).
- **C안 inotify 데몬**: 이벤트 구동이나 **장수 데몬 = 세션사멸과 동일 실패모드** → 결국 systemd 로 살려야 함 → 단독 비권장.
- 결론: **A(이벤트) 또는 B(최소·견고)** 중 회장 택1. C 비권장. ★ 어느 쪽도 cokacdir cron 은 relay-only, 실행은 OS driver 가 sh/py runner 직접 실행(doctrine).

## 2. 감지 대상
- `memory/events/task-*.result.json` (P0-a finish-task result.json-only 산출). 신규 생성분만.
- driver 는 경로만 추출해 `pickup_once(result_json_path)` 호출. 내용 판정은 runner 책임.

## 3. lock / 중복 방지
- pickup_once 는 **락-free 유지**(P0-a 결정). 중복안전 = dedupe 4-tuple(`callback_4tuple_index.jsonl`) + `*.pickup.done` terminal marker + idempotent no-op.
- **driver 레벨 single-flight** 만 추가: crontab runner 는 driver 전용 `flock`(예: `/run/anu-pickup.driver.lock`)로 스캔 중첩 방지(pickup_once 내부 락 아님). systemd oneshot 은 트리거당 직렬화.
- driver 재호출은 항상 안전(처리완료분 no-op).

## 4. result.json quarantine
- schema 검증 실패 / 과대 / foreign / self-key → `memory/events/quarantine/` 로 이동 + 로그, **wake 미발사**.
- `verify_collector_authoritative` 기존 분류(SELF_COLLECTOR_QUARANTINE / PENDING_OWNER_PROOF) 활용. ANU key 아닌 owner → quarantine.

## 5. terminal marker
- `*.pickup.done`(P0-a 4차 atomic write·os.replace) = 처리완료 → driver/pickup skip.
- ANU 소비 후 `*.pickup.acked`. dedupe 원장 = `callback_4tuple_index.jsonl`(task_id+sha256).

## 6. ANU key sealing
- ANU key 는 driver 스크립트/argv/env/systemd unit/crontab 라인 **어디에도 literal 0**.
- runner 내부에서 `utils.env_loader`/`.env.keys` 로만 런타임 로드(sealed). driver 는 **result.json 경로만** 전달.
- wake cron 빌드 = `anu_runner_pickup_and_fire`(executor self-key REFUSE, ANU key sealed).

## 7. 실패 / 재시도 / 증거 마커
- verdict enum: WAKE_BUILT(성공) / PICKUP_SKIP(처리완료) / QUARANTINE(무효·self-key) / FIRE_FAILED(cron 등록 실패).
- 증거: `memory/events/p0b_driver_runs.jsonl`(ts·result_path·verdict·wake_built·error) per-invocation append.
- 재시도: cron 등록 transient 실패 시 **bounded N=3 backoff**, 초과 시 `DRIVER_FIRE_FAILED` marker + 회장 escalation(무한 재시도 금지). systemd Restart=on-failure + StartLimitBurst / crontab 다음 tick(idempotent).

## 8. rollback / disable
- **default DISABLED**: driver 는 `memory/state/p0b_driver_enabled`(flag 파일) 부재/false 시 **전면 no-op**. 회장이 pilot 후 활성.
- systemd: `systemctl --user disable --now anu-pickup.path` (코드 잔존). crontab: 라인 제거.
- 이중 안전: pickup_once `FIRE_NOT_ACTIVATED`/activation_flag 로 실 cron 발사 추가 게이팅.
- pilot: low-risk 단일 task 1회 → 5단계 증거(dev result.json만 → OS event 감지 → pickup → ANU key wake → 독립 세션 spawn) 확인 후에만 active 판정·상시 활성.

## 회장 결정 대기 항목
1. driver 방식 A(systemd path) vs B(crontab poll) 택1
2. 설치 위치: user-level(--user, lingering) vs system-level(root)
3. pilot task 선정 + active 승격 5단계 증거 기준 확정
4. 승인 시에만 P0-b task md 작성·dispatch (현재 dispatch 금지)
