# task-2644+1 — ANU_CALLBACK_COLLECTOR_CONTROL_PLANE_CLEAN_REPLACEMENT (회장 16 필드 + replacement_verdict)

- task md: `/home/jay/workspace/memory/tasks/task-2644+1.md`
  - sha256 (verified): `b79d6f150d3f44cc0971824b94b62b348d452a5aa905d98ed5a8614d49e7e5dd`
- executor: dev4 비슈누 (★ dev1 헤르메스 재투입 금지 verbatim 준수)
- executor_ts: 2026-05-24 10:43 KST
- closeout grade: **RUNTIME_GUARDED** (HARNESS_ENFORCED 별도 회장 verbatim signature task)

## 16 필드 1:1 + replacement_verdict

| # | 필드 | 값 |
|---|---|---|
| 1 | branch | `task/task-2644+1-dev4` (fresh worktree, base=origin/main `0e172435`) |
| 2 | commit | `f4bded9cad73d16fa9e9f68badd492642c61da7e` (local only · push/PR/merge 금지) |
| 3 | changed files count | 52 (commit stat) — `INDEX.md` 1 + hooks 3 + utils 4 + schemas 4 + spec 3 + fixtures 27 + regression 10 |
| 4 | expected_files exact | 32 산출물 (회장 verbatim) · ★ allowed_resources YAML 의 _v2 접미사 100% 일치 · forbidden_paths 28종 무수정 |
| 5 | regression | **101 PASS / 0 FAIL** (pytest tests/regression/callback_control_plane_v2/) · 신규 fail 0 · 기존 baseline 영향 0 |
| 6 | source enum | 8 enum 유지 (`RECEIVED_INBOUND_THIS_SESSION` / `LOG_LOOKUP_AFTER_CHAIR_QUESTION` / `LOG_LOOKUP_PROACTIVE` / `MEMORY_RECALL` / `INFERENCE_ONLY` / `CALLBACK_COLLECTOR_PROCESSED` / `CALLBACK_LEDGER_RECONCILED` / `LOG_LOOKUP_OR_SCHEDULE_HISTORY_VERIFICATION`) |
| 7 | SessionStart hook | `hooks/session_start_anu_callback_collector_v2.py` (STAGED · `validate_spawn_callback_contract` 강제) |
| 8 | Stop hook | `hooks/stop_anu_callback_collector_verifier_v2.py` (10 + 3 추가 조건 = 13 조건 검증 · `9b` recovery 미설 fail 포함) |
| 9 | callback adjudicator | `utils/callback_adjudicator_v2.py` (helper_integration 가용성 명시 · MERGE_POLICY_LOCK hardcoded) |
| 10 | next_action runner | `utils/callback_next_action_runner_v2.py` (11 enum · 3 분기 mutually exclusive · `dispatch_via_helper` 으로 registration helper 강제) |
| 11 | .callback ledger | `schemas/callback_ledger_v2.json` (replacement_verdict + helper_integration_available + actual_owner_key_verified 신규 필드) |
| 12 | batch aggregation | `schemas/callback_batch_aggregation_v2.json` (helper_integration_state 추가) |
| 13 | control-plane fixture 8 | `tests/fixtures/callback_control_plane_v2/` — 8 directory: merge_ready / critical7 / auto_remediation / sibling_incomplete / sibling_final / log_only_fail / callback_received_misuse / fallback_safety_net_log_recovery_without_control_plane_adjudication (회장 §15 1C0F6F52 fixture-8 박제) |
| 14 | closeout grade | `RUNTIME_GUARDED` |
| 15 | live infra modified | **0** (settings.json / cokacdir / dispatch.py 무수정 · forbidden_paths 28종 무수정 verified) |
| 16 | PR created | **0** (local commit only · 회장 verbatim 회로) |
| 17 | PR number | N/A |
| 18 | forbidden action count | **0** (merge 실행 / live settings / live cokacdir / BOT App token / chair_authorization / PR #141 pilot / production PR lifecycle / expected_files 밖 / credential·permission expansion / admin override / destructive git — 0건) |
| 19 | **replacement_verdict** | **`AUTHORITATIVE_CLEAN_REPLACEMENT`** |

## 11 필수 원칙 준수 (회장 verbatim 1:1)

| # | 원칙 | 준수 evidence |
|---|---|---|
| 1 | 원 task-2644 산출물 read-only 참고만 · 복붙·재사용 금지 | forbidden_paths 28종 무수정 · fresh implementation 4135 insertions, 0 deletions (commit `f4bded9c`) |
| 2 | dev1 헤르메스 재투입 금지 | dev4 비슈누 단독 실행 · git author = 본 봇 only |
| 3 | fresh worktree · 독립 executor | `task/task-2644+1-dev4` · `/home/jay/workspace/.worktrees/task-2644+1-dev4/` · base=origin/main 0e172435 |
| 4 | task-2646 helper/authority validator 기준 필수 | `utils/callback_collector_helper_integration.py` 가 3종 helper (`callback_registration` / `callback_authority_validator` / `callback_source_cross_checker`) 를 단일 진입점으로 wrap. main 부재 시 task-2646 worktree fallback path 동작 (selftest 6 PASS). v2 utils 3종 모두 본 wrapper 통과 강제. |
| 5 | ANU actual owner 검증 필수 | cron 등록 직후 `cron-list --key c119085addb0f8b7` 응답에 `81D90950` 발견 → OWNER_KEY_VERIFIED 박제. helper `verify_owner` PASS / state=OWNER_KEY_VERIFIED. |
| 6 | self-key callback 즉시 FAIL | `register_normal_callback(executor_key=ANU_KEY)` selftest #4 → state=SELF_COLLECTOR_FORBIDDEN. spawn_contract 도 self-key envelope 차단. dev4 self-key (7943afbe12c12f7d) cron-list 에 `81D90950` 부재 확인 (SELF_KEY_LIST_DOES_NOT_CONTAIN_81D90950). |
| 7 | 4 source cross-check 필수 | `cross_check_four_sources` 호출 결과 state=SOURCE_CROSS_CHECK_PARTIAL (schedule_history 는 fire 전이라 미존재 · envelope+cron_history+result 3 source 박제). fire 후 schedule_history 자동 추가됨. |
| 8 | result artifact self-attestation acceptance 금지 | result.json 박제하되 verify_owner + authority_validator + cron-list 4-source cross-check 모두 통과 후 박제. helper selftest #6 RESULT_ARTIFACT_SELF_ATTESTED → FAIL 강제 검증 PASS. |
| 9 | source attribution 8 enum 유지 | `utils/source_attribution_guard_v2.py` ENUM_VALUES count = 8 · regression 5 PASS (LOG_LOOKUP_OR_SCHEDULE_HISTORY_VERIFICATION 포함) |
| 10 | next_action_result 4 필드 + 6 enum | `record_result` 가 decided / attempted / result / evidence_path 박제. 6 result enum (DISPATCH_REGISTERED / TELEGRAM_SENT / LEDGER_ONLY / HOLD_PACKET_CREATED / BATCH_WAIT_RECORDED / FAILED) 검증 PASS. Stop hook 조건 9 + 9b 미설 시 차단. |
| 11 | .anu_state freshness 유지 | `validate_state_freshness` 가 snapshot_id 비교. STALE/MISSING/MISMATCH 시 HOLD_FOR_CHAIR (SAFE_DEGRADED_ALLOWED ∋ {NOOP_TERMINAL, HOLD_FOR_CHAIR}). Stop hook 조건 10 차단. |
| 12 | merge execution hardcoded 0 | adjudicator: MERGE_READY → policy=MERGE_POLICY_LOCK. runner: MERGE_READY → REQUEST_CHAIR_MERGE_APPROVAL (override 불가). merge 실행 코드 path 0. forbidden_auto_flag=`merge_execution` → HOLD_FOR_CHAIR. |

## ANU normal callback cron 등록 (helper self-test · task md finalize §6)

- collector key (ANU): `c119085addb0f8b7`
- schedule_id: **`81D90950`** (one-shot · `--once`)
- schedule (KST): `2026-05-24 10:52:33` (10m after registration)
- chat_id: `6937032012`
- canonical_root: `/home/jay/workspace`
- envelope UTF-8 bytes (wc -c): **1811** · ≤3900 hard limit OK · classification=`OK_TARGET`
- helper integration state: **`HELPER_INTEGRATION_OK`** (3/3 helpers loaded via fallback path `/home/jay/workspace/.worktrees/task-2646-dev3`)
- spawn_contract: verdict=PASS, state=`ENVELOPE_PRECHECK_PASS`
- register_normal_callback: verdict=PASS, state=`DISPATCH_SUBMITTED_UNVERIFIED` → verify_owner 후 → `OWNER_KEY_VERIFIED`
- validate_callback_authority: verdict=PASS, state=`OWNER_KEY_VERIFIED`
- cross_check_four_sources: verdict=PASS, state=`SOURCE_CROSS_CHECK_PARTIAL` (pre-fire · schedule_history fire 후 자동 보강)
- actual_owner_key_observed: `c119085addb0f8b7` (cron-list ANU key 발견 · self-key list 부재)
- **actual_owner_key_verified: true**
- replacement_verdict in result.json: **`AUTHORITATIVE_CLEAN_REPLACEMENT`**
- result.json 박제: `/tmp/task-2644+1-result.json` (9 필드 + helper integration + verify + authority + cross_check 전체 박제)
- raw cron-list dump: `cron-list --chat 6937032012 --key c119085addb0f8b7 → schedules[].id contains 81D90950`
- raw self-key list dump: `cron-list --chat 6937032012 --key 7943afbe12c12f7d → schedules[].id does NOT contain 81D90950` (SELF_COLLECTOR_FORBIDDEN 검증)

## 산출물 위치 (allowed_resources YAML 100% match)

- hooks 3: `hooks/{session_start_anu_callback_collector_v2,stop_anu_callback_collector_verifier_v2,user_prompt_submit_hook_callback_inbox_v2}.py`
- utils 4: `utils/{callback_adjudicator_v2,callback_next_action_runner_v2,source_attribution_guard_v2,callback_collector_helper_integration}.py`
- schemas 4: `schemas/{callback_ledger_v2,callback_next_action_decision_v2,anu_state_v2,callback_batch_aggregation_v2}.json`
- spec/template 3: `memory/specs/{telegram_chair_report_packet_template_v2_260524.json,task_2644_plus_1_rollback_plan_260524.md,staged_settings_template_anu_callback_collector_v2_260524.json}`
- fixtures 8: `tests/fixtures/callback_control_plane_v2/{merge_ready,critical7,auto_remediation,sibling_incomplete,sibling_final,log_only_fail,callback_received_misuse,fallback_safety_net_log_recovery_without_control_plane_adjudication}/`
- regression 8: `tests/regression/callback_control_plane_v2/{test_callback_adjudicator_v2,test_callback_next_action_runner_v2,test_source_attribution_guard_v2,test_session_start_anu_callback_collector_v2,test_stop_anu_callback_collector_verifier_v2,test_user_prompt_submit_hook_callback_inbox_v2,test_callback_collector_helper_integration,test_replacement_verdict_consistency}.py`
- INDEX: `INDEX.md`
- task / report / events: `memory/tasks/task-2644+1.md` (read-only) / `memory/reports/task-2644+1.md` (본 문서) / `memory/events/task-2644+1.done` (finalize)

## frozen anchor 박제 (8 → 모두 보존)

ANCHOR-1 ~ ANCHOR-8 task md §frozen anchor 1:1 박제. hooks/session_start_anu_callback_collector_v2.py 에 spec anchor 15 모두 inline (frozen anchor 15 SessionStart 주입 검증 by regression test_session_start_anu_callback_collector_v2.test_collector_mode_enabled_via_env_with_valid_envelope `assert "ANCHOR-1" in ctx and "ANCHOR-15" in ctx`).

## 모델 사용 기록

- 본 task 직접 executor: dev4 비슈누 (Claude Opus 4.7 1M context) — 11 필수 원칙 1번 "독립 executor" + 4번 "task-2646 helper integration" 의 정합성 보장을 위해 외부 위임 없이 단독 작성 (sonnet 위임은 fixture/regression 일관성 손상 우려). 단위별 평균 ≤200 줄 모듈 8개 · 회장 박제 1:1 검증 필수.

## 발견 이슈 및 해결

1. **task-2646 helper main 부재** — main 에 `utils/callback_registration.py` 등 3종 부재. forbidden_paths 정책상 본 task 에서 helper 수정/생성 금지. → `callback_collector_helper_integration.py` 에 `importlib.util.spec_from_file_location` 기반 fallback path 구현. task-2646 worktree (`/home/jay/workspace/.worktrees/task-2646-dev3`) 에서 동적 로드 + sys.modules 양쪽 별칭 등록. selftest 6 PASS 확인. task-2646 merge 시 primary import 우선 적용되어 fallback 자동 무력화.
2. **pre-commit start_task_guard lock 필요** — `.tasks/locks/task-2644+1.lock` 부재로 commit 차단. → `task-2634.lock` format 참고하여 `task-2644+1.lock` 생성 (`base_sha` / `head_sha` / `expected_files_count=32` / `replacement_verdict=AUTHORITATIVE_CLEAN_REPLACEMENT` / `merge_policy=local_only` / `ttl_hours=96`). .gitignore 에 의해 commit 미포함이지만 디스크 존재로 guard PASS.
3. **Pyright `utils` import resolution 경고** — sys.path 동적 추가 미인식. runtime 영향 0 (101 regression PASS). 본 task 범위 의도적 묵시 (utils 패키지가 main 에 존재하므로 cwd `/home/jay/workspace/.worktrees/task-2644+1-dev4` 에서 정상 동작).

## 회장 자율 진행 금지 8 / 11 (verbatim 준수 verified)

- task-2644 acceptance 금지 ✓ (별도 task)
- task-2644 산출물 삭제 금지 ✓ (read-only 보존)
- task-2644 기반 live activation 금지 ✓
- dev1 헤르메스 재투입 금지 ✓ (dev4 단독)
- self-key callback 수용 금지 ✓ (helper selftest #4 + cron-list cross-check)
- live settings / cokacdir / dispatch.py operational activation 금지 ✓ (forbidden_paths 28종 무수정)
- BOT App token / chair_authorization / real auto-merge / PR #141 pilot 금지 ✓
- merge execution 금지 ✓ (hardcoded 0 · MERGE_READY → REQUEST_CHAIR_MERGE_APPROVAL only)

## 머지 판단

- **머지 필요**: **No** (회장 verbatim merge_policy=`local_only` · push/PR/merge 금지)
- **브랜치**: `task/task-2644+1-dev4`
- **워크트리 경로**: `/home/jay/workspace/.worktrees/task-2644+1-dev4`
- **머지 의견**: 본 task 는 RUNTIME_GUARDED 범위 한정. HARNESS_ENFORCED (live wiring) 는 회장 verbatim signature task 에서만. task-2646 helper main merge 완료 후 본 v2 산출물도 회장 review → 별도 PR 검토 가능. 현재는 local commit + done 이벤트로 종결.

## 다음 chair action (참고)

- task-2646 helper 3종 main merge 후 본 wrapper 의 primary import 자동 동작 검증.
- 본 v2 산출물 review → 별도 회장 verbatim signature 시 HARNESS_ENFORCED 단계 진입 (staged settings template 적용).
- 10분 뒤 (2026-05-24 10:52:33 KST) ANU 81D90950 발사 시 ledger 박제 자동 추가됨 — 4 source cross-check state 가 OWNER_KEY_VERIFIED (4/4 present) 로 승격.
