# TASK2752 — ANU-side Owner Adoption / Re-signing Model (Design Packet)

상태: `TASK2752_REAL_DEV_RESULT_OWNER_ADOPTION_MODEL_DESIGN_AND_IMPLEMENTATION_APPROVED_ACTIVE_FALSE`
작성: 2026-06-15 KST / ANU (설계만 — ANU 직접코딩 금지) / 회장 승인 기반
목표 상태: real dev/executor result.json 을 ANU pickup runner 가 **검증 후 ANU-owned adoption artifact 로 입양**하여 owner-proof 를 부여. ACTIVE=false 유지.

---

## 0. 문제 정의 (task-2751 pilot 실증)
- real dev result(task-2751, dev2 작성)는 sealed ANU owner-proof 부재 → `owner_key_class=FOREIGN` → owner_proof_pickup_gate 가 `owner_unprovable` 로 QUARANTINE. cron 0·spawn 0.
- idle-window(1D87E3AC) PASS 는 ANU 자작 fixture(owner_key_class=ANU)였기 때문 — **self-authored 경로만 검증됨**.
- ★ 따라서 real executor result 를 normal callback 으로 수거하려면 owner adoption 모델이 필요.

## 1. 설계 목적 (gate 약화 절대 아님)
- dev result 는 **끝까지 untrusted executor output** 으로 유지.
- dev 에게 ANU key/token/proof 를 **주지 않음**(option C 기각 사유 = self-collector 경계 흐려짐).
- ANU pickup runner 가 **검증 책임을 지고** dev result 를 adopt → **ANU-owned adoption artifact** 가 owner-proof 를 가짐.
- source dev result 는 **불변**, `source_result_sha256` 으로 원본 무결성 연결.

## 2. 기존 재사용 가능 인프라 (신규 아님 — 확장)
- `dispatch/anu_collector_result.py`: **`CollectorResult`** 스키마에 이미 **`source_result_sha256`** + **`owner_proof: OwnerProof`** 필드 존재. `write_collector_result`(atomic·fsync), `collector_result_path`(`<task_id>.collector_result.json`) 존재. → **adoption envelope = 이 collector_result 구조 재사용**.
- `dispatch/anu_result_pickup_runner.py`:
  - `owner_proof_pickup_gate`(line ~1170): ② eligibility(`_read_gate_eligibility`/`_gate_eligibility_ok`, rule_7 self-collector 차단) ③ runtime sealed ANU key(`is_anu_key`) ④ freshness(head_sha==canonical).
  - `build_owner_gate_fn`(line ~1319): driver 가 주입하는 gate fn.
  - pickup_once 처리순서 8~10: ledger → collector_result write → done marker (ANCHOR-B durability).
- `dispatch/anu_pickup_driver.py`: `process_one` 이 `owner_key_class` 판정(ANU/FOREIGN) → FOREIGN+unprovable → QUARANTINE.

## 3. 핵심 설계 — Owner Adoption Gate (신규 단계)
현재: `owner_key_class==FOREIGN` → 즉시 QUARANTINE(owner_unprovable).
신규: FOREIGN 이어도 **Adoption Validation Gate** 통과 시 → `ADOPTED_BY_ANU` → ANU 가 collector_result(owner_proof=ANU sealed) 생성.

### 3.1 신뢰 모델 (불변)
- gate ③(runtime sealed ANU key)는 **"ANU pickup runner 가 실행 중"**을 계속 증명(유지). 이건 dev result 의 owner 가 아니라 **adoption 주체가 ANU 임**을 보장.
- dev result 의 owner_key_class 는 FOREIGN 으로 **정직하게 유지**(세탁 아님). adoption artifact 에 `adopted_from=FOREIGN`·`adoption_decided_by=ANU` 명시.

### 3.2 Adoption Validation Gate (전부 hard-fail = quarantine)
FOREIGN dev result 가 adopt 되려면 **아래 전부 PASS**:
1. **dispatch record 존재**: `memory/capabilities/<task_id>.json` 또는 dispatch ledger 에 해당 task_id capsule 기록 존재(미존재 → quarantine 또는 PENDING_OWNER_PROOF).
2. **capsule_sha / task_id 일치**: result.task_id == dispatch record task_id, capsule_sha 일치(mismatch → quarantine).
3. **scope 일치**: result.scope_id == 활성 pilot scope(밖 → 처리 0).
4. **source path 정합**: result 가 watched inbox 의 정규 경로(`p0b_inbox/<task_id>.result.json`).
5. **source_result_sha256**: adoption 시 계산한 sha256 == artifact 기록값(불일치 → quarantine).
6. **schema 유효**: 필수필드(task_id/completion_signal/owner_pickup_required/authoritative/...) 충족.
7. **terminal_status 유효**: PASS/PASS_WITH_WARNINGS/PARTIAL 중 하나.
8. **eligibility(기존 ②)**: authoritative=false · schedule_created_by_executor=false · callback_fired_by_executor=false(rule_7 self-collector 차단 유지).

### 3.3 Adoption 산출물 (ANU-owned)
- `<task_id>.collector_result.json` (기존 writer 재사용):
  - `adopted_by_anu: true`
  - `adopted_from: "FOREIGN"`
  - `adoption_decided_by: "ANU"`
  - `source_result_sha256: <원본 result sha256>`
  - `source_result_path: <원본 경로>` (불변)
  - `capsule_sha / dispatch_task_id`: dispatch identity 연결
  - `owner_proof`: ANU sealed-key 기반 proof(adoption artifact 가 ANU 소유임을 증명)
  - `scope_id`, `terminal_status`(원본에서 복사), `relay_hints`(원본에서 복사)
- source dev result: **변조 0**(읽기만). adoption 후 source 는 processed/ 로 이동(불변 보존) 또는 그대로 두고 marker 로 종결.
- 이후 **callback/wake 는 collector_result(adoption artifact) 기준으로만** 진행(원본 result 기준 아님).

## 4. 판정 분기 (11 필수 검증 조건 매핑)
1. valid real dev result → **ADOPTED_BY_ANU** ✅
2. valid real dev result → ANU-owned collector_result 생성 ✅
3. valid real dev result → owner_proof 통과(adoption artifact owner_proof=ANU) ✅
4. source_result_sha256 일치 검증 ✅ (불일치 → quarantine)
5. capsule_sha / task_id mismatch → **quarantine** ✅
6. dev callback schedule claim(callback_schedule_created=true 또는 cron 흔적) → **quarantine** ✅
7. dev self-key claim → **quarantine** ✅
8. self-collector claim → **quarantine** ✅
9. missing dispatch record → **quarantine 또는 PENDING_OWNER_PROOF**(재시도 여지) ✅
10. stale epoch result → **skip/quarantine** ✅ (기존 legacy_cutoff 재사용)
11. duplicate result → **idempotent**(ledger dedupe (task_id, sha256) 재사용 — 재adoption 0, 재발사 0) ✅

## 5. 구현 위치 (dev2 bounded)
- `dispatch/anu_result_pickup_runner.py`: owner_proof_pickup_gate(또는 신규 `owner_adoption_gate`) 에 **FOREIGN→adoption 분기** 추가. gate ③(sealed ANU runtime key)는 adoption 주체 증명으로 유지.
- `dispatch/anu_collector_result.py`: CollectorResult 에 adoption 필드(`adopted_by_anu`/`adopted_from`/`adoption_decided_by`/`source_result_path`/`capsule_sha`/`dispatch_task_id`) 추가(스키마 v2, 하위호환).
- `dispatch/anu_pickup_driver.py`: process_one 의 FOREIGN→QUARANTINE 단락을 **FOREIGN→adoption gate** 호출로 교체(adoption 실패 시에만 quarantine).
- 신규 helper: `validate_for_adoption(result, dispatch_record, ...)` (순수함수, 8 검증).
- ★ 모든 신규는 **opt-in flag(default OFF)** 또는 contract 분기 — 기존 self-authored 경로 무손상. ACTIVE=true 아님.

## 6. 보안 경계 (비협상)
1. dev 는 ANU key/token/proof 0 (adoption 후에도).
2. adoption 은 ANU pickup runner 단독 — dev/executor 가 self-adopt 불가.
3. owner_proof(adoption artifact)는 sealed ANU key 기반 — 서명 경로 dev 노출 0, raw key 기록 0.
4. validation gate 는 hard-fail(부실 검증 = untrusted→trusted 세탁 통로 금지).
5. source result 불변 + sha256 연결(위변조 추적).
6. self-collector/self-key/callback-schedule claim → 무조건 quarantine.

## 7. 테스트 요구 (dev2 — 회귀)
- 11 검증조건 각각 1+ 테스트(ADOPTED 1건, quarantine 7분기, pending 1, skip 1, idempotent 1).
- adoption artifact owner_proof=ANU·source_result_sha256 일치·source 불변 검증.
- 기존 self-authored(idle-window) 경로 회귀 무손상.
- raw key 0(출력/artifact).
- py_compile + 기존 P0-B 회귀 전체 PASS.

## 8. dev2 위임 범위 / 금지
- 허용: 위 5 구현 위치 코드 + 회귀 테스트 + bounded PR 후보 생성.
- 금지: merge/push(회장 승인 전) · ACTIVE=true · 3-gate 활성화 · systemd/daemon 수정 · cron 직접 생성 · raw key 기록 · self-collector · 기존 self-authored 경로 변조 · gate 약화(검증 hard-fail 완화).
- 산출물: PR 후보 + result.json(p0b_inbox, 단 이번엔 ANU 가 별도 수거 안 함 — TASK2752 는 code 작업이라 일반 finish-task/PR 경로).

## 9. 단계 (회장 작업방식 준수)
1. ✅ ANU design packet(본 문서) 작성.
2. → 회장 보고.
3. → dev2 code 위임(bounded PR).
4. → CI/회귀 PASS + Gemini.
5. → merge **회장 승인 대기**.
6. ACTIVE=true 금지 유지.

---
**상태**: `TASK2752_..._DESIGN_PACKET_WRITTEN_ACTIVE_FALSE` · ACTIVE=false · 다음=회장 보고 후 dev2 위임.
