# task-2717 — ANU_OWNED_CALLBACK_ENFORCEMENT (Phase 1/2 분리)

> 회장 최종 보정 2026-05-31. 단일소스. self-collector 재발을 문서/sh-읽기 의존이 아니라 **OS-level 강제 실행 경로**로 막는다.

## 핵심 정정 (회장 verbatim)
- **cokacdir cron ≠ 강제 실행**. `cokacdir --cron`은 OS 명령 직접 exec 아님 — 에이전트 세션을 깨워 prompt 를 읽게 함. "Run scripts/...sh" 짧게 써도 여전히 prompt(에이전트 읽기) 의존.
- 목표 = **OS-level 강제 실행**. sh 를 "읽게" 말고 dispatch/OS-cron/hook 가 "실행하게".

## 최종 원칙 (7)
1. old executor-created normal callback **폐기**.
2. dev 봇은 callback schedule 생성 0.
3. dev 봇은 **result JSON 만** 작성.
4. ANU-owned runner 가 result JSON pickup.
5. pickup/검증/격리/closeout 판단은 **sh/py runner 가 코드로** 수행.
6. cokacdir 에이전트 cron = 판단/실행 경로 아님, **terminal JSON relay 전용**.
7. 가능하면 runner 가 직접 sendfile/보고까지 → 에이전트 의존 최소.

## 강제 실행 방식
- OS crontab / systemd timer / **systemd path unit / inotify** 중 하나. ★result JSON 생성 순간 pickup 가능한 **systemd-path 또는 inotify 우선 검토**(폴링 0 = "계속 체킹" 자체 제거).
- OS-level runner 가 `scripts/anu_callback_pickup.sh` 직접 실행.
- **sh = lock/env/entrypoint**, **py = schema/owner proof/quarantine/closeout logic** 분리.

## hook/key 보안
- **PreToolUse / shell guard = PRIMARY 게이트.**
- executor 세션의 `cokacdir --cron` 호출 차단 또는 `SELF_CALLBACK_ATTEMPT` 기록.
- executor vs ANU runner 구분 = prompt 아닌 **dispatch 가 주입하는 신뢰 role env**(예: `COKACDIR_ROLE=executor`).
- **ANU key 를 dev bot prompt 에 노출 0**. ANU key 는 봉인 위치에서 ANU-owned runner 만 사용.
- owner proof = envelope 문구 아님 → **actual schedule owner/key 또는 OS runner identity** 로 검증.

## 멱등성
- runner = task 단위 lock. terminal marker 이미 있으면 no-op. push/Gemini/resolve = **exactly-once**. retry/fallback/manual re-entry 겹쳐도 이중 FF push·이중 Gemini·이중 resolve 0.

---

## Phase 1 = TRUST 제거 / 탐지 (먼저, 별도 PR)
- py runner: result JSON schema 검증 / actual owner proof 검증 / `SELF_COLLECTOR_QUARANTINE` / `PENDING_OWNER_PROOF` / `NO_RESULT_JSON` / `AUTHORITATIVE_CALLBACK` 결정적 status
- terminal marker 멱등 lock
- result JSON schema (`schemas/anu_task_result.schema.json` 또는 동등)
- **기존 self-collector 자동 격리**(즉시 효과: 위조 callback 탐지·격리)
- regression: dev self-key spoof / access denied schedule / stale envelope 재사용 / ANU-owned 정상 / result JSON pickup / quarantine path
- **dev1 기존 산출물(7f644a1a, `dispatch/anu_owned_callback_enforcement.py`, branch task/task-2717-anu-owned-callback-enforcement)이 Phase 1 후보** — ANU 독립 재검증(self-collector 주장 불신) 후 Phase 1 PR 판단.

## Phase 2 = NEED 제거 / 예방 (다음, 별도 PR)
- completion_contract 자동 주입(dispatch 단계, `callback_creation_allowed=false`·`collector_authority=ANU_ONLY`·`pickup_runner`)
- dev prompt 에서 ANU key 제거 (+ 봉인 위치 이전)
- executor callback cron 생성 차단 hook(PreToolUse) + `COKACDIR_ROLE` 주입
- **OS-cron / systemd-path / inotify 기반 pickup** + `scripts/anu_callback_pickup.sh` entrypoint
- result JSON only completion 표준화 + cokacdir cron = relay only 격하
- latency 계측: 0~2분 normal / ~5분 retry / ~30분 dead-man(사용 시 `CALLBACK_LATENCY_DEGRADED`)

## 분리/금지
- **한 PR 과적 금지 — Phase 1 / Phase 2 별도 PR.**
- **PR #162 판단과 task-2717 구현 계속 분리.** PR #162 = 현재 HARD_STOP / NOT MERGE_READY 유지.
- task-2713 CALLBACK_LOCATION_METADATA / task-2715 REMEDIATION_HEAD_ADVANCE 와 정렬, 중복 0.
- CI workflow 수정 0 · closeout_marker_watcher 신규 0 · task-2703 혼입 0 · 각 구현 PR 은 runtime-code-only.

## 순서
1. dev1 Phase 1 산출물(7f644a1a) ANU 독립 재검증 → Phase 1 PR(회장 인가).
2. Phase 2 dispatch(회장 인가) — OS-level 강제 실행 + hook + contract + key 봉인.
