# task-2635+1 — normal callback registration enforcement 정정 (status schema 5축 분리)

- Level: Lv.3 (정정 · 회장 PARTIAL_PASS_WITH_REQUIRED_FIX 후속)
- 담당: dev6 페룬
- base: task-2635 dev6 본인 로컬 commit **bf2cca7a** (origin/main 5ffa87ae 위)
- 단일소스 spec: `memory/specs/system_normal_callback_registration_implementation_spec_260523.md` + 본 task md
- 회장 판정: PARTIAL_PASS_WITH_REQUIRED_FIX (산출물 25 / 신규 regression 69 PASS / baseline 264 PASS 인정. envelope payload registration_status 정합성 결함만 차단)

## 회장 verbatim 정정 사유
**envelope payload 의 registration_status 가 NOT_REGISTERED 로 남아 있는데, 보고서와 self-hardening 실증은 REGISTERED 로 설명하고 있다. 이 불일치는 normal callback registration enforcement 의 핵심 필드 정합성 문제다. 문서/보고서 문제가 아니라 result/envelope schema 의미가 흔들리는 문제이므로 PR open 전에 수정해야 한다.**

실측 확인 (cron 8A9EB65E 회수 history):
- envelope payload (cron prompt 내부): `registration_status="NOT_REGISTERED"` · `cron_schedule_id=None` · `attempted_callback_registration=True` · `delivery_method="anu_cron_callback"`
- 실제 cron 등록 결과: 성공 (id=8A9EB65E 회수)
- 원인: envelope build 가 `register_normal_callback` 호출 **이전** 에 수행되어 결과 미반영. register 호출 후 envelope payload 의 status/schedule_id 필드 갱신 누락.

## 필수 정정 (회장 7 항목 verbatim)

### 1. status schema 5축 분리 (단일 `registration_status` → 5 필드)
```
registration_intent              — callback 등록 의도 (bool) · True 가 기본 (회장 사전 면제 명시 시만 False)
registration_attempted           — 실제 registrar 호출 시도 (bool)
registration_result_status       — 시도 결과 enum:
                                     REGISTERED · NOT_REGISTERED · REGISTER_FAILED · SENDFILE_ONLY · SKIPPED_WITH_EXPLICIT_REASON
callback_delivery_status         — 봇→cokacdir→ANU 전달 단계 enum:
                                     PENDING · DELIVERED · UNDELIVERED · NOT_APPLICABLE
collector_receipt_status         — ANU collector 수령 단계 enum:
                                     UNCONFIRMED · RECEIVED · TIMED_OUT · NOT_APPLICABLE
```

기존 `registration_status` 단일 필드는 deprecated 표시(폐기 노트 추가) 또는 `registration_result_status` 로 직접 이름 변경 — 권장: **이름 변경 + 5축 명시**.

### 2. REGISTERED 기록 조건
`registration_result_status = REGISTERED` 는 **실제 cron schedule_id 가 생성된 뒤에만** 기록. envelope build 시점 사전 기록 금지.

### 3. NOT_REGISTERED 기록 조건
`registration_result_status = NOT_REGISTERED` 는 **cron 등록 시도 자체가 없거나 sendfile-only** 인 경우에만 기록.

### 4. envelope 최종 등록 결과 정확 반영
register 성공 후 envelope payload 갱신 (build-then-register 순서 reverse 또는 register-after-update 패턴):
- `registration_result_status` = REGISTERED
- `cron_schedule_id` = 실제 schedule id (e.g. `8A9EB65E`)
- `registered_at_ts` = 실제 등록 시각
- `attempted_callback_registration` = True
- `delivery_method` = `anu_cron_callback`

### 5. 용어 일관화
`report.md` / `result.json` / `callback-envelope.json` 의 status 용어 동일 (5축 enum 정본 기준).

### 6. 추가 fixture (5 시나리오 신규)
`tests/fixtures/normal_callback_registration/<scenario>/{evidence.json,expected.json,PROVENANCE.md}`
- `registered_schedule_id_present` → result=REGISTERED + schedule_id present + delivery=DELIVERED + receipt=UNCONFIRMED→RECEIVED 흐름
- `sendfile_only_not_registered` → intent=True · attempted=False · result=SENDFILE_ONLY · delivery=NOT_APPLICABLE · receipt=NOT_APPLICABLE
- `attempted_but_register_failed` → intent=True · attempted=True · result=REGISTER_FAILED + error_message · delivery=UNDELIVERED · receipt=NOT_APPLICABLE
- `registered_but_not_yet_received` → result=REGISTERED + schedule_id + delivery=DELIVERED + receipt=UNCONFIRMED (TTL 미경과)
- `received_by_anu_collector` → result=REGISTERED + delivery=DELIVERED + receipt=RECEIVED (durable-success 마커 확인)

### 7. regression 강화 (모순 조합 FAIL)
`tests/regression/test_callback_registration_enforcement.py` 또는 신규:
- `registration_result_status == NOT_REGISTERED` + `cron_schedule_id != None` → **FAIL** (모순)
- `registration_result_status == REGISTERED` + `cron_schedule_id == None` → **FAIL** (모순)
- `registration_attempted == False` + `registration_result_status in (REGISTERED, REGISTER_FAILED)` → **FAIL** (모순)
- `registration_result_status == SENDFILE_ONLY` + `attempted_callback_registration == True` → **FAIL** (모순)
- `callback_delivery_status == DELIVERED` + `registration_result_status != REGISTERED` → **FAIL** (모순)
- `collector_receipt_status == RECEIVED` + `callback_delivery_status != DELIVERED` → **FAIL** (모순)

## 허용 (회장 verbatim)
- expected_files 내부 수정
- regression 보강
- 로컬 추가 commit
- ANU normal callback 재검증 (정정 schema 기반 새 envelope 발사)

## 금지 (회장 verbatim)
- push/PR/merge 금지
- expected_files 밖 수정 금지
- replacement_pr_runner 수정 금지
- finish-task.sh 수정 금지
- foreign dirty 정리 금지
- real auto-merge executor 구현 금지
- NL intake 코드 구현 금지

## expected_files (task-2635+1 범위)
정정 수정 대상:
- `utils/anu_callback_registrar.py` — build-then-register-then-update 로 순서 정정 + 5축 필드 채움
- `utils/callback_envelope_schema.py` — 5축 enum + validator + 모순 조합 검출
- `dispatch/finalize_hooks.py` (있다면) — 5축 결과 propagation
- `memory/reports/task-2635.md` — 신규 작성 (없는 상태 — 회장 5번 "용어 일관화" 필요)
- 신규 fixture 5종 × 3 files = 15
- 기존 fixture 5종 (registered_normal · not_registered_envelope_only · sendfile_only_no_cron · register_failed_cli_error · skipped_explicit_reason_dryrun) 도 5축 schema 반영 갱신
- 신규 regression: `tests/regression/test_callback_registration_status_consistency.py` (모순 조합 FAIL 단언)

총 ~30 files (5 helper/schema/report + 15 신규 fixture + 15 기존 fixture 갱신 + 1 신규 regression). **프로덕션 코드 신규 변경 0** (helper/schema 갱신만).

## 자동수렴
- Gemini medium/style + expected_files 내부 + Critical7 0 + credential expansion 0 → 자동수렴
- 동일 함수 HIGH 반복 시 LOOP_BOUNDARY → 회장 보고

## 안전 불변식
- ANU key `c119085addb0f8b7` 하드코딩 단일 출처 유지
- envelope UTF-8 ≤3900 bytes 유지
- live cokacdir 실호출 0 (regression mock/dry-run)
- replacement_pr_runner / finish-task.sh / merge_ready_classifier / merge_ready_dryrun_executor **무수정**
- expected_files 외부 수정 0

## finalize 프로토콜 (★ 로컬 한정)
1. base = 본인 commit bf2cca7a (origin/main 5ffa87ae 위) clean
2. 정정 수정 + 신규 fixture 5 + 기존 fixture 5 갱신 + 신규 regression PASS + 기존 69+264 유지 + full new fail 0
3. **로컬 commit만** (push/PR/merge 금지)
4. ANU normal completion callback 재검증 — **정정된 register helper 사용**: build-then-register-then-update 순서로 envelope payload 의 5축 모두 정확 반영
5. envelope 최종 payload (cron prompt 내부) 확인 필수:
   - `registration_result_status` = REGISTERED (string)
   - `cron_schedule_id` = 실제 id (non-null string)
   - `registered_at_ts` = 실제 ts (non-null)
   - `attempted_callback_registration` = True
   - `delivery_method` = "anu_cron_callback"
   - `registration_intent` = True
   - `registration_attempted` = True
6. 회수 후 본 task 종료 callback cron-history 의 prompt payload 도 위 값 정확히 일치하는지 자기검증

## frozen anchor
- ANCHOR-1: "envelope payload 최종 5축 상태 정확 반영 — build-then-register-then-update 순서"
- ANCHOR-2: "status schema 5축 분리 (intent · attempted · result · delivery · receipt) · 단일 필드 의미 흔들림 차단"
- ANCHOR-3: "모순 조합 (schedule_id 존재 + NOT_REGISTERED 등) regression FAIL 단언"
- ANCHOR-4: "기존 fixture 5 갱신 + 신규 fixture 5 = 10 시나리오 5축 enum 정합"
- ANCHOR-5: "push/PR/merge 금지 · 로컬 commit + ANU callback 재검증 까지만"
