# task-2720+2 — PR #166 P0-a 2차 bounded fix: lock 단순화 + 타임존 ISO 파싱

## 회장 인가 (2026-06-01)
PR #166(head `0d8c3522`) 1차 fix 후 새 High 3건(466 타임존 파싱 / 231·396 lock race). Critical7 아님.
회장 결정 = **② lock 단순화 방향 2차 bounded fix**. 목표 = MERGE_READY_CANDIDATE.
★ 2차 fix 후에도 새 High 반복 시 **추가 fix 금지 → LOOP_BOUNDARY 보고**.

## worktree
- `/home/jay/workspace/.worktrees/task-2720-dev1` (branch `task/task-2720-dev1`, head `0d8c3522`)에서 **이어서**. base origin/main `5e714887`.

## expected_files (5개 — 그 외 수정 금지)
1. `dispatch/anu_owned_callback_enforcement.py` (이식분 — 466 타임존 수정 허용, blob 깨짐 보고서 명시)
2. `tests/regression/test_anu_owned_callback_enforcement_2717.py`
3. `dispatch/anu_result_pickup_runner.py`
4. `tests/regression/test_anu_result_pickup_runner_2720.py`
5. `scripts/finish-task.sh`
(evidence: memory/events/task-2720+2.done · memory/reports/task-2720.md 갱신 허용)

## 수정 1 — pickup runner 파일락 단순화 (231/396 race 해소)
- **stale lock 회수 / lock-stealing / _STALE_LOCK_SECONDS / token 검증 로직 제거 또는 비활성화**.
- P0-a 는 파일락을 필수 동시성 제어로 보지 않는다. 멱등성은 **dedupe(4-tuple) + terminal done-marker + idempotent no-op** 중심.
- 동시 호출이어도 **wake 중복 0** 을 dedupe/marker 로 보장(파일락 race 없이).
- 락이 꼭 필요하면 best-effort 단순 락(획득 실패 시 no-op)만 — stale 회수/탈취 로직 없음.

## 수정 2 — 이식모듈 `_parse_timestamp_value` 타임존 ISO 파싱 (466)
- `"Z"` suffix(기존 writer) + `"+09:00"` 류 timezone offset ISO 모두 파싱.
- `datetime.fromisoformat`(Py3.7+, `Z`→`+00:00` 치환) 활용. naive/aware 비교 오류 없게 **tz-aware 정규화**(_envelope_age_seconds 비교 일관).
- **기존 Z-suffix writer 경로 유지**(회귀 0). 이식 blob 깨짐 → 보고서에 명시.

## regression (최소 포함)
- timezone offset(`+09:00`) timestamp 파싱 → 정상 age 계산(stale 오인 0)
- Z suffix 기존 timestamp 파싱(회귀 0)
- 동시 pickup 2회 → **중복 wake 0**(dedupe/marker)
- terminal done-marker 존재 → no-op
- stale lock/lock-stealing race **재발 방지 또는 해당 로직 제거 확인**(락 단순화 입증)
- 기존 28~29 PASS 유지/증가

## 검증 (finalize 전)
- `python3 -m pytest tests/regression/test_anu_result_pickup_runner_2720.py tests/regression/test_anu_owned_callback_enforcement_2717.py -q` 전 PASS.
- `git diff --name-only origin/main` = 코드 5(+evidence). ANU key literal 0 유지. active 완료주장 0 유지.
- semantic 3조건 유지: T2626_ANU_KEY=0 / callback-launch.json 생성=0 / result.json 작성=1.

## 금지 (회장 verbatim)
merge 금지 · **push 금지(ANU 수행)** · admin override 금지 · force push/rebase 금지 ·
expected_files 밖 수정 금지 · OS-level crontab/systemd/inotify 설치 금지 · PR #163 close/merge 금지 ·
과거 memory/scripts ANU key literal sanitize 금지 · active 완료 주장 금지.
★ 2차 fix 후 새 High 반복 시 추가 fix 금지 → LOOP_BOUNDARY 보고.

## finalize (로컬 commit 까지만)
1. fix → regression PASS → `git add` expected_files → 로컬 commit. **push/PR/merge 금지.**
2. `memory/reports/task-2720.md` 에 2차 처리내역(466 FIXED+blob깨짐 / 231·396 lock 단순화 / dismiss 유지분) 추가.
3. `memory/events/task-2720+2.done` 생성. ANU key(c119085, sealed) callback. ★ ANU key literal 노출 0.

## ANU 후속 (봇 아님 — governance)
ANU 독립 재검증 → FF push → OWNER `/gemini review` 1회 + dismiss thread resolve →
CI 11/11 + unresolved 0 + CLEAN/MERGEABLE + diff 5파일 + ANU key 0 + active 0 →
MERGE_READY_CANDIDATE / LOOP_BOUNDARY / HOLD_CRITICAL7 판정. merge 회장 승인 전 금지.

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "dispatch/anu_owned_callback_enforcement.py"
    - "tests/regression/test_anu_owned_callback_enforcement_2717.py"
    - "dispatch/anu_result_pickup_runner.py"
    - "tests/regression/test_anu_result_pickup_runner_2720.py"
    - "scripts/finish-task.sh"
    - "memory/events/task-2720+2.done"
    - "memory/reports/task-2720.md"
  forbidden_paths:
    - ".github/**"
    - "anu_v2/ci_gemini_watcher_runner.py"
    - "anu_v2/ci_gemini_watcher_gh_adapter.py"
  commands:
    - "pytest"
    - "python3 -m pytest"
    - "python3 -m py_compile"
    - "gh"
  merge_policy: "none"
  ttl_hours: 48
```

## ★ dispatch 템플릿 G3(PR/머지) 무시. finalize 로컬 commit only 우선. finish-task --action pr 금지.

## goal_assertions (auto-generated)
- `python3 -m pytest tests/regression/test_anu_result_pickup_runner_2720.py tests/regression/test_anu_owned_callback_enforcement_2717.py -q`
