# task-2680 — CALLBACK_SELF_KEY_REGISTRATION_HARDENING_FIX_IMPLEMENTATION 결과 보고

- 담당: dev2 오딘
- chair_authorization_id: `CHAIR-AUTH-CALLBACK-SELF-KEY-HARDENING-FIX-20260526-JJONGS-IMPLEMENT-001`
- 완료 상태: **`CALLBACK_SELF_KEY_REGISTRATION_HARDENING_FIX_IMPLEMENTED`**
- date: 2026-05-26
- merge_policy: `fix_implementation_separate_pr_no_merge_chair_signature_required`

## 1. 수정된 파일 list

### 신설 (4 파일)
- `utils/callback_authority_4source_validator.py` (★ 470 lines, 4-source 교차검증 pure-function gate)
- `tests/callback_authority_4source/__init__.py`
- `tests/callback_authority_4source/test_4source_validator.py` (★ 29 케이스 regression)
- `memory/specs/system_callback_authority_4source_verify_doctrine_260526.md` (★ doctrine 박제)

### 보강 (3 파일)
- `utils/anu_callback_registrar.py` (★ `_build_cokacdir_cron_argv` 내부 `_assert_independent_anu_key(anu_key)` 추가 + `assert_cron_argv_uses_anu_key` 신설)
- `utils/callback_collector_helper_integration.py` (★ `classify_collector_authority_4source` + `emit_anu_independent_reverify_request` wiring 추가 · 분류 enum 5종 재노출)
- `dispatch/normal_fallback_callback_helper.py` (★ `assert_argv_uses_anu_key` 신설 + `build_anu_owned_callback_request` 의 argv post-build verifier 추가)

### Event / report (3 파일)
- `memory/events/task-2680.callback-self-key-hardening-fix-result-260526.json`
- `memory/events/task-2680.done`
- `memory/reports/task-2680.md` (본 파일)

## 2. 6 수정 목표 각각 구현 evidence

| # | 목표 (회장 verbatim) | 구현 evidence | regression |
|---|---|---|---|
| 1 | task md ANU key 명시인데 실제 cron self-key 등록 방지 | `_build_cokacdir_cron_argv` 내부에 `_assert_independent_anu_key(anu_key)` 강제 + `classify_collector_authority` 가 actual cron-history query 로 fire-후 탐지 | R1 3건 PASS |
| 2 | helper --key 인자 cron layer 강제 | `assert_cron_argv_uses_anu_key` (registrar) + `assert_argv_uses_anu_key` (helper) + `build_anu_owned_callback_request` post-build argv verifier | R2 6건 PASS |
| 3 | actual owner key 검증 callback collector gate | `classify_collector_authority_4source` 가 collector spawn 시점에 cokacdir --cron-history 의 actual --key 를 ANU + executor self-key 2회 query 로 직접 채록 | R3 2건 PASS |
| 4 | self-key callback NON_AUTHORITATIVE_SELF_COLLECTOR 자동 분류 | classification enum 5종 + transition table (S2.self_count>=1 AND anu_count<=0 → SELF_COLLECTOR) + `classify_from_observed` fast-path | R4 6건 PASS |
| 5 | ANU independent reverify flow 강제 | `build_anu_independent_reverify_request` 가 NON_AUTHORITATIVE_* / UNDETERMINED_* / PROMPT_DRIFT 시 ReverifyRequest 객체 build · integration layer 의 `emit_anu_independent_reverify_request` 가 caller-facing API 노출 | R5 4건 PASS |
| 6 | regression (self-key 재발 방지 + 4 source 교차 + collector gate) | 29 케이스 regression suite + Track A (91DDBCDA→78F385CF dev4 7943afbe12c12f7d) · Track J (A6200C2F→33E60E8B dev5 109fa85250c6d46b) 사고 1:1 재현 anchor | R6 6건 + Track A/J 2건 PASS |

## 3. regression suite 추가 list

`tests/callback_authority_4source/test_4source_validator.py` 29 케이스:
- R1 group (3): track A/J self-key detection + ANU happy path
- R2 group (6): registrar argv builder + cron-layer assert + helper assert_argv + build_anu_owned_callback_request
- R3 group (2): collector gate wiring + actual owner overrides envelope text
- R4 group (6): classify_from_observed 5 transition table cases + reverify trigger membership
- R5 group (4): build_reverify_request + emit_anu_independent_reverify_request
- R6 group (6): history_gap / dual_owner / prompt_drift / subprocess_error / evidence_completeness / to_json_roundtrip
- Track 1:1 재현 (2): Track A 91DDBCDA·78F385CF · Track J A6200C2F·33E60E8B

## 4. pytest PASS / FAIL count

```
============================== 29 passed in 0.20s ==============================
```

command: `WORKSPACE_ROOT=$(pwd) python3 -m pytest tests/callback_authority_4source/ -v --tb=short`

- 통과: 29 / 29 (100%)
- 실패: 0
- 소요: 0.20s

## 5. file overlap

| 항목 | 변경 파일 수 | 비고 |
|------|-------------|------|
| PR #149 코드 (`utils/anu_codex_micro_refinement_loop.py` · `utils/codex_cc_decision_loop.py` · `tests/anu_codex_micro_refinement_loop/**`) | **0** | 금지 1 1:1 |
| PR #150 코드 (`utils/pr_watcher_terminal_state_classifier.py` · `tests/pr_watcher_terminal_state_classifier/**`) | **0** | 금지 2 1:1 |
| task-2662~2679 event/file | **0** | (memory/events/task-26{62..79}* 변경 0) |
| Axis runtime | **0** | 금지 3 |
| live settings.json | **0** | 금지 4 |
| hooks/** | **0** | 금지 5 |
| dispatch.py (31 line shim) | **0** | 금지 6 |
| HARNESS_ENFORCED 전체 선언 | **0** | 금지 7 |
| auto-merge | **0** | 금지 8 |
| 기존 PR merge | **0** | 금지 9 |
| `.github/**` | **0** | forbidden_paths |
| `schemas/**` | **0** | forbidden_paths |
| `/home/jay/.claude/**` | **0** | forbidden_paths |
| `memory/specs/v3_*`, `memory/specs/worktree_promotion_*`, `memory/specs/pr_watcher_*` | **0** | forbidden_paths |
| `memory/specs/callback_self_key_registration_*` (★ task-2677 파일) | **0** | forbidden_paths — 본 packet 은 `system_callback_authority_4source_verify_doctrine_260526.md` 신규 파일 사용 |

## 6. forbidden_action_count

- 합계: **0**

verified by:
- `git status` (commit 전): 변경 파일 모두 allowed_resources.paths 매핑
- forbidden_paths 그룹별 grep 검증
- read_only_reference (task-2677 worktree · callback_self_key_root_cause_audit.json) 만 참고용 read 만 수행

## 7. PR 개시 여부

- branch: `task/task-2680-dev2` (origin/main 기반)
- worktree: `/home/jay/workspace/.worktrees/task-2680-dev2`
- PR 권장 사항: 본 packet 은 **별도 PR** (task md `merge_policy = fix_implementation_separate_pr_no_merge_chair_signature_required`)
- merge: **금지** — 별도 chair signature 강제
- main divergence 안내: main 에는 본 worktree 의 origin/main 베이스에 없는 `utils/callback_collector_helper_integration.py` 가 별도로 존재 (main 5 commits ahead). 본 packet 의 보강은 main 의 파일을 1:1 복사 + 함수 추가 형태로 진행 → main merge 시 충돌 가능성, 회장 결정 시 main 의 비공식 commit 5개를 push 또는 본 branch 의 add 와 merge 정책 결정 필요.

## 8. 4 source 교차 doctrine evidence

| Source | 코드 hook | 본 packet 채용 |
|--------|----------|---------------|
| S1 schedule_history | `_read_schedule_history` (JSONL 마지막 line parse) | ✓ |
| S2 cron-history     | `_query_cron_history` (cokacdir CLI subprocess · ANU + executor self-key 2회) | ✓ |
| S3 envelope         | `_parse_envelope_from_prompt` (JSON-우선, regex fallback) | ✓ |
| S4 result artifact  | `_read_result_artifact` (memory/events/<task_id>.*-result-*.json glob) | ✓ |

전 source 의 evidence 는 `AuthorityClassification.evidence` (FourSourceEvidence dataclass) 에 audit-trail 박제. `to_json()` 으로 직렬화 가능. regression `test_r6_evidence_has_4_sources` 가 4 source 모두 노출 확인.

## 9. recommended next action

1. **회장 별도 chair signature 발급** — merge 전 신규 ID (`CHAIR-AUTH-CALLBACK-SELF-KEY-HARDENING-MERGE-<TS>-...`) 권장.
2. **PR review** — Gemini code-assist 대기 (5분) → 미수정 High 0건 시 merge 권한 가능. 본 packet 은 helper signature 보존 + post-build verifier additive 패턴이라 high-severity 발생 가능성 낮음.
3. **main divergence 해소** — origin/main 과 main 사이 5 commit 차이. 본 PR base 가 origin/main 이므로 main 의 callback_collector_helper_integration.py 와 conflict 가능. push 시 conflict 발생하면 회장에게 conflict 해소 정책 보고.
4. **봇 finalize 경로 wiring 별도 task 권장** — 본 packet 은 helper layer + integration wiring 까지. RC3 (BOT_AUTONOMOUS_FIRE) 의 완전 차단은 `scripts/finish-task.sh` 의 callback runner 결선 (task-2677 fix_diff_preview §3) 이 별도 task 로 필요. 본 task 의 범위 외 (task md `forbidden_paths` 에 `scripts/finish-task.sh` 포함 0 이지만 task md 허용 9 list 에 finish-task.sh 변경 명시 0).
5. **ANU normal callback cron 발사** — 본 보고 직후 ANU key c119085addb0f8b7 로 envelope-only callback 30s 후 fire (task md `종결` 1:1).

## 머지 판단

- **머지 필요**: Yes (★ 단, 별도 chair signature 강제 · 본 봇 직접 merge 0)
- **브랜치**: `task/task-2680-dev2`
- **워크트리 경로**: `/home/jay/workspace/.worktrees/task-2680-dev2`
- **머지 의견**: helper signature 보존 + additive post-build verifier 패턴이므로 정상 import 경로에 영향 0. main 의 callback_collector_helper_integration.py 와 충돌 가능성 있어 회장 결정 권장. regression 29/29 PASS · 6 수정 목표 모두 evidence 박제.

## 모델 사용 기록

- 본 task 의 코드/문서 작성은 팀장(Opus 4.7) 직접 수행. 이유: helper 결선 핵심 변경 + chair_authorization 명시 task 로 위임 분기 0건의 단일 PR. 팀원 위임 없음.

## 발견 이슈 및 해결

| 이슈 | 해결 |
|------|------|
| origin/main 베이스에 `utils/callback_collector_helper_integration.py` 부재 (main 만 보유) | main 의 파일을 worktree 로 복사 후 보강. branch 분기 anchor 기록 (§7 main divergence 안내) |
| pytest 환경에서 dispatch package import 시 main repo 가 우선 캐시되어 sub-module 못 찾는 현상 | `_load_helper_module` helper 가 sys.modules 의 `dispatch*` 캐시 정리 + worktree path 강제 우선 후 `importlib.import_module` 호출. 모든 regression PASS |
| Pyright import resolution 경고 다수 (utils.* / dispatch.*) | pyright 환경 변수 미설정 (워크트리 격리 환경 특성). pytest 실 import 는 정상 PASS — pyright 경고는 무시 가능 (런타임에 영향 0) |
| 기존 anu_callback_registrar.py 의 NormalCallbackRegistrationStatus / _delay_to_at_value 미사용 경고 | task-2680 범위 외 (기존 파일의 historic state). 본 packet 변경과 무관 — 별도 lint task 권장 |

성공: **`CALLBACK_SELF_KEY_REGISTRATION_HARDENING_FIX_IMPLEMENTED`**
