# task-2762 보고서 — P0B event-strategy LIVE owner_gate 시그니처 정합 micro-fix

- 작업 ID: task-2762
- 팀: dev1-team (헤르메스 팀장 / 불칸 백엔드 / 아르고스 테스터)
- 목표 상태: `P0B_EVENT_STRATEGY_OWNER_GATE_SIGNATURE_MICROFIX_PR_READY_ACTIVE_FALSE`
- PR: https://github.com/Jeon-Jonghyuk/dev_workspace/pull/245
- 브랜치: `task/task-2762-dev1` (base: main `8420a763`)

---

## S (Situation) — 상황
WIRED_CANDIDATE 라이브 경로의 owner-proof 게이트는 `build_owner_gate_fn` 팩토리가 반환하는
`_gate` 호출자에 의해 평가된다. 실 호출부는 `executor_key` 를 kwarg 로 전달하도록 설계되어 있다.

## C (Complication) — 문제
`build_owner_gate_fn` 반환 `_gate` 가 `def _gate(result_json_path)` — **위치인자 1개만** 수용했다.
그러나 실 호출부 `dispatch/anu_pickup_driver.py::_provenance_callback_bridge`(line 254)는
`owner_gate_fn(result_path, executor_key=callback_executor_key)` 로 **executor_key kwarg** 를 전달한다.
→ 실 factory 사용 시 `TypeError` → bridge except 포착 → `BRIDGE_OWNER_GATE_FAIL` → callback fire
영구 미도달. 회귀테스트가 `owner_gate_fn=lambda *a, **k: _Gate(...)` permissive lambda 로 결함을 가렸다.

## Q (Question) — 질문
호출 계약(`owner_gate_fn(p, executor_key=...)`)과 반환 `_gate` 시그니처를 어떻게 정합시키되,
self-collector 방어를 약화시키지 않고 driver 경로 회귀 0 을 보장할 것인가?

## A (Answer) — 해결
**1축 최소 수정.** `dispatch/anu_result_pickup_runner.py::build_owner_gate_fn` 반환 `_gate` 를
`_gate(result_json_path, *, executor_key=None)` 로 보정.

- factory-bound `executor_key` 를 `bound_executor_key` 로 캡처(내부 동명 kwarg shadowing 방지).
- 정합 규칙(보수적 merge): `effective_executor_key = call-time executor_key (비어있지 않으면) else bound`.
  - 비어있지 않은 call-time executor_key 는 **반드시** self-collector 체크에 반영(무시로 약화 금지).
  - 없거나 빈 문자열이면 factory-bound 값으로 폴백.
- `owner_proof_pickup_gate` **시그니처/본문 불변** → self-collector 방어 ③단계
  (`if executor_key and runtime_key == executor_key: → FAIL_CLOSED_NON_ANU_KEY`) 그대로 보존.
- driver 경로는 bound `""` + call `callback_executor_key=""` → effective `""` → **동작 동일(회귀 0)**.
- 반환 타입 어노테이션 `Callable[[str], …]` → `Callable[..., …]` 로 정정.

### owner_gate 시그니처 정합 방식 (요약)
선호 방향 #1(회장 verbatim) 채택 — 호출부(driver) 변경 0, runner `_gate` 1곳만 보정.

### self-collector 방어 보존 근거
owner proof 정책 함수 `owner_proof_pickup_gate` 는 **한 글자도 수정하지 않음**. `_gate` 는 effective
executor_key 산출만 담당하고 동일 정책에 그대로 전달. 비어있지 않은 call-time executor_key 가 들어오면
self-collector 체크(`runtime_key == executor_key`)에 반드시 반영됨(테스트 4가 self-key/foreign-key
차단을 증명). permissive 우회 0.

---

## 수정 파일 목록
1. `dispatch/anu_result_pickup_runner.py` — `build_owner_gate_fn` 반환 `_gate` 시그니처 정합 (+15/-4)
2. `tests/regression/test_p0b_owner_gate_signature_2762.py` — 신규 회귀테스트 6항목 (+326)

(runtime code PR only — memory/reports/plans/artifact 혼합 0)

## diff 요약
```
 dispatch/anu_result_pickup_runner.py               |  19 +-
 tests/regression/test_p0b_owner_gate_signature_2762.py | 326 +++++++++
 2 files changed, 341 insertions(+), 4 deletions(-)
```

## 테스트 결과 (6/6 PASS — 실제 build_owner_gate_fn, permissive lambda 아님)
1. `test_real_factory_not_permissive_lambda` — PASS (실 factory 산출 callable)
2. `test_executor_key_kwarg_no_typeerror_reaches_gate` — PASS (kwarg 전달 TypeError 0 + 위치인자 회귀 0)
3. `test_gate_ready_anu_owner_proof_proceeds` — PASS (`OWNER_PICKUP_READY_NO_FIRE`, LIVE_PENDING 아님)
4. `test_self_key_and_foreign_key_blocked` — PASS (self-key/foreign-key → `FAIL_CLOSED_NON_ANU_KEY`)
5. `test_bridge_path_real_owner_gate_no_typeerror` — PASS (실 `_provenance_callback_bridge` import, TypeError 0)
6. `test_no_real_callback_fire` — PASS (spy only, real fire 0)

기존 회귀: 신규 수정과 무관한 선행 FAIL 6건 확인(audit_decision_check 5 / sealed_key dedupe 1 — 수정 전부터
동일 상태). 2760 wiring 테스트 파일은 main 미존재(2760 미머지) — main 기준 회귀 영향 없음.

## L1 스모크테스트 결과
- 서버 재시작: 해당없음 (라이브러리/dispatch 코드 변경, 기동 서버 없음)
- API 응답 확인: 해당없음 (HTTP 엔드포인트 아님)
- 실동작 확인(코드 레벨 L1): 실 `build_owner_gate_fn` + 실 `_provenance_callback_bridge` import 후
  `owner_gate_fn(result_path, executor_key="")` 직접 호출 →
  - `BRIDGE_OWNER_GATE_FAIL` 아님(= TypeError 미발생, owner gate 평가 도달) ✓
  - `REAL_FIRE_COUNT: 0` (callback spy only, 실 cokacdir/systemd/cron 발사 0) ✓
  - 수정 전이라면 동일 호출이 TypeError → 항상 fire 0 이었음(결함 재현/해소 대조 확인)
- 스크린샷: 해당없음 (UI 아님)
- pytest: 신규 6 PASS + py_compile OK

## 불변식 / 안전
- real callback fire 0 · ACTIVE=false · 3 flag OFF 유지
- controlled adapter(permissive) 우회 0 · activation 0 · systemd enable 0 · recurring cron 변경 0
- admin override 0 · ledger robustness/matching 미착수 · callback/result contract 미확장
- expected scope 내 수정만 (dispatch runner 1곳 + 테스트 1파일)

## CI / Gemini 상태
- PR #245 open. Gemini 자동 리뷰는 **인간 트리거만 유효**(bot `/gemini review` 무효) — 미도착 시
  분류: `GEMINI_REVIEW_TRIGGER_REQUIRED` (Critical 아님). long-polling/CI 대기 미진입(doctrine 준수).
- **merge 금지** — 회장 승인 전까지 PR open 까지만. same-PR push/commit/amend 금지(Gemini 도착 후).

## 모델 사용 기록
- 헤르메스(팀장): Opus — 설계/분배/검토/통합/PR (직접 코딩 0, G1 설계만)
- 불칸(백엔드): Sonnet — `_gate` 시그니처 보정 구현
- 아르고스(테스터): Sonnet — 회귀테스트 6항목 작성/실행
- haiku 미사용 (dispatch 안전성 핵심 로직 — sonnet 이상 적용)

## 발견 이슈 및 해결
- (해결) 신규 테스트 pyright 2건(어노테이션 `R.OwnerProofGateResult.__class__` / 미사용 `_EXEC_KEY` import)
  → `_make_gate` 반환 어노테이션 제거 + foreign-key 케이스에 `_EXEC_KEY`(EXECUTOR_SELF_KEY_EXAMPLE) 사용으로 정리.
- (환경) 비표준 worktree 경로로 `start_task_guard.py` 검증#1 불통 → 훅 공식 우회(`TASKCTL_BYPASS=1` + reason,
  evidence 자동 기록)로 commit/push. 런타임 fix(972b0929)는 정규 micro-commit.

## 머지 판단
- 머지 필요: No (회장 승인 대기 — task doctrine "merge 금지 · PR open 까지만")
- 브랜치: task/task-2762-dev1
- 워크트리 경로: /home/jay/.cokacdir/workspace/C197E935/wt-2762
- 머지 의견: 1축 최소 변경, owner_proof_pickup_gate 불변으로 self-collector 방어 보존, 회귀 0, 테스트 6 PASS.
  Gemini 인간 트리거 리뷰 후 High 0건 시 머지 적격. PR-only 상태로 회장 판단 대기.

## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회

