# task-2720+3 — pickup runner 파일락 완전 제거 (보강 · 회장 명시)

상태: **implemented + verified + wired 후보** · **active 아님** (active 는 P0-b 별도 승인 후 판단).
finalize: **로컬 commit only** — push/PR/merge 0 · force-push/rebase 0 · admin override 0 · PR #163 보존(close/merge 0) · `finish-task --action pr` 0 · OS-level 설치 0.
base: origin/main `5e714887` · HEAD `93bf053c`.

> 본 +3 보고서는 `task-2720.md`/`.done`(lock-기반 +1 서술, 28 tests)의 **최종 상태 갱신**이다. +2 에서 lock 단순화 + tz 파싱, +3 에서 lock 완전 제거가 적용되어 이전 서술이 stale 해졌으므로 본 문서가 권위 evidence다.

## 1. 핵심 변경 (High #209 — stale-lock liveness 결함)
이전 구현은 `<task>.pickup.lock` 을 `O_CREAT|O_EXCL` 로 생성해 동시성 제어 → 직전 pickup 프로세스가 비정상 종료(SIGKILL/시스템 다운)하면 lock 이 영구 잔존, 해당 task_id 의 모든 pickup 이 영구 차단되는 **liveness 결함**(Gemini High #209). +1 에서 mtime 기반 stale 회수(`_STALE_LOCK_SECONDS`)로 우회했으나 회수 자체가 또 race 표면.

**+3 결정: lock 메커니즘 자체를 완전 제거.** 동시성은 lock 이 아니라 멱등성으로 보장한다 → 결함의 근본 원인(lock)이 사라지므로 회복코드 없이 **결함 소멸(dissolve)**.

### Critical gate (회장 verbatim, PASS 조건)
```
grep -E 'pickup\.lock|_lock_acquired|_STALE_LOCK|lock.?steal|O_EXCL' \
     dispatch/anu_result_pickup_runner.py
```
→ **0 건 (PASS)**.

## 2. 중복 wake 방지 = lock-free 멱등성 3중
lock 제거 후에도 중복 wake 0 을 보장하는 3중 멱등 경로 (`pickup_once`):
1. **terminal-marker no-op** (L184-190): `<task>.pickup.done` / `.pickup.acked` 존재 시 즉시 `SKIP_TERMINAL` no-op.
2. **dedupe ledger** (L192-216): 기존 `memory/events/callback_4tuple_index.jsonl` 재사용, `(event=PICKUP_WAKE_BUILT, task_id, sha256)` 매칭 시 `SKIP_DEDUPE` no-op.
3. **idempotent done-marker 작성** (L315-329): WAKE_BUILT 성공 시 done marker 기록 → 후속 호출은 (1)에서 차단.

모든 차단 경로는 `wake_built=False, argv=None` no-op `PickupResult` 반환 — 부수효과(실 발사·schedule·fs mutation) 0. lock 없이도 동일 (task_id, sha256) 의 재실행은 wake 0.

## 3. 타임존 fromisoformat 유지
`dispatch/anu_owned_callback_enforcement.py :430` `_parse_timestamp_value` — +2 에서 적용한 `datetime.fromisoformat` 기반 tz-offset(`+09:00`) / `Z`-suffix 파싱 **유지 (본 +3 미변경)**. 본 모듈은 +2 tz-fix 로 PR#163 head `b257f2aa` blob 과 더 이상 동일하지 않으나, 이는 인가된 변경이며 task 요구사항("타임존 fromisoformat 유지")을 충족한다.

## 4. semantic 유지 (finish-task.sh) — 3조건 PASS
- `grep -c 'T2626_ANU_KEY' scripts/finish-task.sh` = **0** (하드코딩 키 제거)
- `callback-launch.json` 생성 = **0**
- `executor-write-result` (result.json 작성 경로) = **1**

## 5. ANU key literal 노출 0 (Critical7 gate)
task-2720 도입분(코드 5 + evidence 2)에서 ANU 독립키 literal **0건**:
finish-task.sh · anu_result_pickup_runner.py · anu_owned_callback_enforcement.py · 두 regression test · 본 +3 .done/report 전부 0.
ANU key 는 `_default_sealed_key_loader` 가 `utils.env_loader.load_env_keys()` → `os.environ["COKACDIR_KEY_ANU"]` 로만 로드(미로드 시 fail-closed wake 0) — argv/prompt/literal 노출 0.

> 사전존재 관찰(scope 외 · 무수정): 트리 내 과거 정상인가 파일(`anu_v3/*`, `config/callback_policy.json`, `dispatch/callback_owner_enforcer.py`, `memory/backups/*`, 과거 task report 등)에 동 literal 이 존재한다. **"과거 ANU key sanitize 금지"** 원칙 + scope guard 상 본 task 는 손대지 않음. 정리 여부는 회장 판단 대상으로 보고만 함.

## 6. scope guard — code 5개 PASS
`git diff --name-only origin/main` (코드):
- `dispatch/anu_owned_callback_enforcement.py`
- `dispatch/anu_result_pickup_runner.py`
- `scripts/finish-task.sh`
- `tests/regression/test_anu_owned_callback_enforcement_2717.py`
- `tests/regression/test_anu_result_pickup_runner_2720.py`

= **5개 (PASS)**. evidence(`task-2720.done/md`, `task-2720+3.done/md`)는 코드 scope 외 별도 허용. 신규 helper 임의생성 0.

## 7. Layer A / NO-CRON
runner 내 subprocess / crontab / systemd / inotify 설치 / merge = 0. grep 매치 2건(L7, L16)은 전부 *부재를 명시한 docstring negation*. 실 발사·OS 설치는 권한 있는 ANU 세션(P0-b driver)이 수행 — 자가발사 0.

## 8. regression — 32 passed (network 0)
```
pytest tests/regression/test_anu_result_pickup_runner_2720.py \
       tests/regression/test_anu_owned_callback_enforcement_2717.py -q
```
→ **32 passed** (pickup_runner 12 + enforcement 20). 전부 mock/fixture, 네트워크 0.
test 9/9b(lock fixture)는 +3 에서 "lock 파일 미생성 fs 검증 · lock 심볼 0건" 으로 재작성됨.

## 9. LOOP_BOUNDARY (회장 verbatim)
본 +3 = **3차 fix**. 이후 동일 semantic(pickup runner lock / liveness / 멱등성)에 대한 신규 High 가 또 반복되면 **추가 fix 금지 → LOOP_BOUNDARY 보고만**. 본 +3 으로 lock 계열 수렴.

## 10. active 경계 · 완료 정의
- 본 task = implemented(코드) + verified(32 PASS) + **wired 후보**. **active 미주장** — active 는 P0-b(OS-level event driver) 5단계 증거 + 별도 승인 후에만 판단. 본 문서에 active/운영중/완료(active) 표현 0.
- 완료 = **ANU key normal callback**. 이후 ANU governance(push→gemini→resolve→MERGE_READY 판정)은 봇 아님 · 본 task 범위 외(회장 승인 전 push/PR 금지).

---
finalize commit (로컬 only): 본 +3 evidence (`task-2720+3.done` + `task-2720+3.md`). HEAD 코드 = `93bf053c`.
verified_at: 2026-06-01T06:19:23+09:00
