# task-2763 — scan_live_inbox_once ↔ callback_launch_fn 시그니처 정합 micro-fix (dev1)

## 목표 (1축만)
Layer A `scan_live_inbox_once` 의 `callback_launch_fn` 호출부를 `build_callback_launch_fn` 반환 `_fn` 시그니처와 정합시킨다. **이 1축 외 변경 금지.** 최소 수정. **새 PR**(PR #245 merged — 재사용 금지).

## 배경 (결함 사실 — 2b′ rerun 중 실 factory 노출)
owner_gate 결함(PR#245/task-2762 수정) 후 owner_gate 가 READY 가 되자, 다음 단계에서 **두 번째 latent wired-path 시그니처 결함**이 드러났다:
- **호출부**: `dispatch/anu_pickup_driver.py` `scan_live_inbox_once` (≈line 1828) = `callback_launch_fn({ "task_id":..., "source_result_sha256":..., "collector_role":..., "owner_proof":... })` — **단일 dict positional** 전달.
- **반환 _fn 시그니처**: `dispatch/anu_callback_launch_audit.py` `build_callback_launch_fn` 의 `def _fn(result_json_path, *, task_id, sha256, executor_key="", schedule_id="", terminal_intent="", relay_required=False)` — **result_json_path positional + task_id/sha256 keyword-only 필수**.
- → 불일치: dict 가 result_json_path 로 들어가고 task_id/sha256 누락 → **TypeError** → callback launch 실패 → FIRE_FAILED → Layer A move/processed 0.
- ★ 회귀테스트/2a canary 는 **mock callback_launch_fn(아무거나 받는 spy)** 으로 이 결함을 가렸다 — 실 build_callback_launch_fn factory 로 처음 노출.
- ★ ANU 정적 점검: scan_live_inbox_once 의 주입 callable 호출부 = busy_fn()(미주입)·owner_gate_fn(p, executor_key=)(수정됨)·callback_launch_fn({dict})(본 결함). **callback_launch_fn 이 Layer A 의 마지막 시그니처 결함**(이후 _move_processed/ledger 는 주입점 아님).

## 수정 방향 (회장 verbatim — call site 명시 인자 전달 우선)
1. **scan_live_inbox_once 가 callback_launch_fn 을 호출할 때 `_fn` 이 요구하는 인자를 명시 전달**: `callback_launch_fn(result_json_path, task_id=<authoritative>, sha256=<canonical digest>, ...)`.
   - `result_json_path` = 실제 result 파일 경로(현재 후보 `p`).
   - `task_id` = target/candidate/result contract 의 **authoritative** 값(현재 scan 이 산출하는 `task_id` = basename 유래 `_legacy_skip_task_id(p)`).
   - `sha256` = **result_json_path 파일 내용의 canonical sha256** (= `_sha256_file(p)`). ★ **payload dict hash / 임의 문자열로 새 의미 정의 절대 금지** — 기존 callback_launch audit 이 기대하는 **파일 digest 의미** 유지. sha256 의미 불명확하면 STOP_REPORT.
   - 기존 dict 의 collector_role/owner_proof 등 부가정보가 _fn 계약에 필요하면 _fn 이 받는 형태로 전달하되, **_fn 계약(result_json_path/task_id/sha256/keyword)을 약화/우회하지 말 것**.
2. **permissive dict adapter(아무거나 받는 `**kwargs`/dict)로 대충 받는 방식 금지.** _fn 이 요구하는 정확한 인자를 명시 전달.
3. callback launch audit / argv hygiene / raw key masking / self-collector 차단 의미 **약화 금지**.
4. `owner_proof_pickup_gate` 정책 변경 금지. `attempt_owner_fire` 정책 변경 금지.

## ★ expected_files (회장 명시 파일 정정 반영)
- **`dispatch/anu_pickup_driver.py`** (scan_live_inbox_once 호출부 — 주 수정 대상. 회장 packet 의 anu_result_pickup_runner.py 는 착오로 보임 — scan_live_inbox_once 는 anu_pickup_driver.py 에 위치).
- (필요 최소 시) `dispatch/anu_callback_launch_audit.py` (_fn 이 부가정보를 받아야 하면 — 단 계약 약화 0).
- `tests/regression/test_p0b_callback_launch_signature_2763.py` (신규 회귀 — 실 factory).
- **이 범위 초과 필요 시 STOP_REPORT.**

## 필수 테스트
1. **실제 `build_callback_launch_fn` factory** 를 사용한 callback_launch signature regression(mock 금지).
2. scan_live_inbox_once live path 가 **TypeError 없이 callback_launch_fn 까지 도달**하는 테스트.
3. **fire_fn 은 fake 유지 → real fire 0**(테스트에서 실 cron 발사 0).
4. owner_gate READY 이후 callback_launch 호출 인자(result_json_path/task_id/sha256) 검증.
5. 기존 `test_p0b_owner_gate_signature_2762.py` 유지 PASS.
6. 기존 `test_p0b_event_strategy_2760.py` / `test_p0b_event_strategy_wiring_2760.py` PASS.

## 금지
real callback fire · 2b′ 재실행 · delivery runner 구현 · systemd enable · recurring cron · production activation · admin override · 기존 p0b_inbox 3건 이동/삭제/소비 · config/constants.json 수정 · canonical root dirty 정리 · Layer A 우회 · direct attempt_owner_fire 단독검증으로 성공처리 · permissive dict adapter · mock-only PASS · hook bypass · 수기 lock.

## STOP 조건 (하나라도 → STOP_REPORT)
expected files 밖 수정 필요 · callback contract 자체 변경 필요 · raw key/argv hygiene 약화 가능성 · self-collector 방어 약화 가능성 · real fire 가능성 · systemd/cron/activation scope · 테스트가 mock 으로만 통과 · **signature fix 후 또 다른 live-path 결함 발견** · conflict 또는 guard bypass 필요.


## ★ 방향 못박기 (회장 추가 보정 verbatim 2026-06-19)
이번 수정은 **callback_launch_fn 계약을 dict 도 받게 넓히는 게 아니다.** scan_live_inbox_once 가 `build_callback_launch_fn._fn` 의 **기존 정식 계약(result_json_path positional + task_id/sha256 keyword)에 맞춰 명시 인자를 전달**하는 방향. 금지: dict positional adapter · `*args`/`**kwargs` permissive · task_id·sha256 optional 완화 · mock-only PASS · audit contract 변경. **sha256 = result_json_path 파일 sha256 고정**(payload dict hash/임의 문자열 신규 의미 금지). 테스트: 실 factory + 호출 인자 정확 전달 검증 + **sha256 == 실제 result_json_path 파일 sha256 일치 검증** + TypeError 사라짐만으로 PASS 금지 + audit argv hygiene/raw key masking/fire 0 유지 + owner_gate READY 이후 callback_launch 도달 live-path regression + fire_fn fake(real fire 0). 추가 STOP: sha256 의미 불명확 · task_id authoritative source 불명확 · callback_launch_fn 계약 완화 필요 · anu_result_pickup_runner.py 수정 필요 · audit/argv hygiene 변함.
## doctrine
- 정식 taskctl/start_task_guard/lock/pre-push hook 우회 0(guard-native). 새 branch `task/task-2763-dev1` · 새 PR. fresh origin/main 91ec3afc 기준.
- runtime code only. Gemini 트리거 금지(ANU owner 발사). long polling 금지. **봇 종료 전 ANU callback 필수**(독립 ANU key `c119085addb0f8b7`, UTF-8 ≤3900 bytes envelope). merge 금지(별도 게이트).

## 보고 요구 (ANU callback envelope + report.md)
task id · branch · PR 번호 · 수정 파일 목록 · diff 요약 · callback_launch_fn 호출↔_fn 시그니처 정합 방식 · task_id/sha256 산출 근거 · self-collector/argv hygiene 보존 근거 · 테스트 결과(6) · CI/Gemini 상태 · real fire 0 · ACTIVE=false · 3 flag OFF.

## 상태명
승인: `P0B_CALLBACK_LAUNCH_SIGNATURE_MICROFIX_APPROVED_ACTIVE_FALSE` / 목표: `P0B_CALLBACK_LAUNCH_SIGNATURE_FIX_PR_READY_ACTIVE_FALSE`

## allowed_resources (본 task의 capability)

```yaml
allowed_resources:
  paths:
    - "dispatch/anu_pickup_driver.py"
    - "dispatch/anu_callback_launch_audit.py"
    - "tests/regression/test_p0b_callback_launch_signature_2763.py"
    - "tests/regression/test_p0b_owner_gate_signature_2762.py"
    - "tests/regression/test_p0b_event_strategy_2760.py"
    - "tests/regression/test_p0b_event_strategy_wiring_2760.py"
  forbidden_paths:
    - "memory/**"
    - "reports/**"
    - "plans/**"
    - ".github/**"
    - "config/constants.json"
    - ".env*"
    - "**/*.done"
    - "dispatch/anu_result_pickup_runner.py"
  commands:
    - "pytest"
    - "python3 -m pytest"
    - "git"
  merge_policy: "manual"
  ttl_hours: 24
```