# task-2721+1 — PR #167 P0-b micro-fix: lock UID 분리 + watcher 피드백 루프 제거 (HIGH 2건)

## 회장 인가 (2026-06-01, Option 1 — HIGH 2건 수정)
PR #167(head `1971d1af`) 독립 파서 기준 fresh HIGH 2건 = 유효 결함, dismiss 금지.
- **HIGH-1**: `/tmp/anu-pickup.driver.lock` 직접 사용 = 멀티유저 충돌.
- **HIGH-2**: `memory/events` 전체 감시 + driver 출력물(jsonl/quarantine/state)을 같은 디렉터리에 기록 = **피드백 루프**(driver 출력이 unit 재트리거).
둘 다 P0-b OS-level driver 안전성 직결. active=false 유지.

## worktree
- `/home/jay/workspace/.worktrees/task-2721-dev1` (branch `task/task-2721-dev1`, head `1971d1af`)에서 **이어서**. base origin/main 29175f80(P0-a 포함).

## expected_files (PR #167 동일 6개 — 그 외 수정 금지)
1. `deploy/systemd/anu-pickup.path`
2. `deploy/systemd/anu-pickup.service`
3. `scripts/anu_pickup_entrypoint.sh`
4. `dispatch/anu_pickup_driver.py`
5. `tests/regression/test_anu_pickup_driver_2721.py`
6. `docs/p0b_driver_runbook_260601.md`
★ `scripts/finish-task.sh` **수정 금지**(고정 — result.json 은 finish-task 가 memory/events 에 작성, 위치 불변). P0-a main 파일 무수정.

## 수정 1 — lock 경로 UID 분리 (HIGH-1)
- `/tmp/anu-pickup.driver.lock` 직접 사용 **금지**.
- 사용자별 충돌 방지 경로: **`${XDG_RUNTIME_DIR:-/tmp}/anu-pickup-${UID}.driver.lock`** (또는 동등한 UID 포함 경로).
- entrypoint(sh)에서 `UID=$(id -u)` 사용. driver-level **flock single-flight 만 유지**. ★ pickup_once 내부 lock 재도입 **금지**(lock-free 유지).

## 수정 2 — watcher 피드백 루프 제거 (HIGH-2)
- ★ **감시 대상 ↔ driver 출력 대상 분리.**
- driver 가 **감시 디렉터리(memory/events) 안에** log/quarantine/jsonl/driver-owned state 를 쓰면 **안 됨**.
- driver 출력물을 **watched path 밖 별도 디렉터리**에 기록(예: `memory/p0b_state/` — driver_runs.jsonl / quarantine / driver state. 경로는 봇 설계, 단 memory/events 밖 필수).
- **unit path 감시 = result input 전용**: `memory/events` 전체 디렉터리 변경 감지가 driver 출력으로 재트리거되지 않게. 권장: PathModified 대신 **input-only glob 패턴**(`PathChanged`/`PathExistsGlob=%h/workspace/memory/events/task-*.result.json`) 또는 driver 출력물을 watched 밖으로 빼서 재트리거 원인 제거. (finish-task 가 result.json 을 memory/events 에 쓰는 것은 불변이므로, **driver 출력 분리**가 1차 해법.)
- ★ quarantine 목적지도 **memory/events 밖**(예: `memory/p0b_state/quarantine/`).
- tmp/partial/다른 marker·jsonl·md = no-op 유지(scan 한정 불변).
- ※ P0-a `pickup_once` 가 쓰는 `*.pickup.done`/`*.pickup.acked` 는 P0-a 소관(무수정). driver 는 **자기 출력물만** watched 밖으로. driver 가 done-marker 존재 시 NOOP_SKIP 으로 재진입 무한루프 방지(idempotent) + driver 출력이 watched 밖이라 **트리거 증폭 제거**.

## 수정 3 — active=false 유지
- 이번 수정 후에도 **installed=false / wired=false / active=false**. capability matrix 과장 금지.

## regression (추가/갱신)
- 기존 11 PASS 유지/증가.
- ★ **lock 경로에 UID/user 분리 반영**: lock path 에 `${UID}` 또는 `id -u` 포함 확인(`/tmp/anu-pickup.driver.lock` 고정문자열 미사용).
- ★ **driver 출력물이 watched path(memory/events) 밖에 기록**되는지 테스트로 확인: driver_runs.jsonl / quarantine 목적지가 memory/events 밖. (mock tmp dir 로 입증)
- default disabled no-op / scan 한정(NOOP_NOT_TARGET) / quarantine(6조건) PASS 유지.
- pickup_once 전부 mock/stub. 실 pickup/wake/ANU key wake 실행 0. key literal 0.

## 검증 (finalize 전)
- `python3 -m pytest tests/regression/test_anu_pickup_driver_2721.py -q` 전 PASS.
- `git diff --name-only origin/main` = 6파일. finish-task.sh 0. ANU key literal net-new **0**.
- lock 경로 `${XDG_RUNTIME_DIR:-/tmp}/anu-pickup-${UID}.driver.lock` 류 확인. `/tmp/anu-pickup.driver.lock` 고정 0.
- driver 출력 경로 memory/events 밖 확인(grep).

## 금지 (회장 verbatim)
- finish-task.sh 수정 금지 · systemctl enable/start/daemon-reload 금지 · unit 실제 설치 금지 · activation flag 생성 금지.
- 실 pickup/wake/ANU key wake 실행 금지 · merge 금지 · force push/rebase/admin override 금지.
- ANU key literal 노출 0(unit/path/service/entrypoint/driver/test/runbook/argv/log/jsonl). pickup_once lock 재도입 금지. P0-a main 무수정.
- ★ gate-parser hardening(gemini badge 탐지)은 **본 PR 미포함**(별도 task).

## finalize (로컬 commit 까지만)
1. fix → regression PASS → `git add` 6파일 → 로컬 commit. **push/PR/merge 금지(ANU 수행)**.
2. `memory/reports/task-2721.md` 에 micro-fix 내역(lock UID 분리 / 출력물 watched 밖 / 피드백 루프 제거) 추가.
3. `memory/events/task-2721+1.done` 생성. ANU key(c119085, sealed) callback. ★ ANU key literal 노출 0.

## ANU 후속 (봇 아님 — governance)
독립 재검증(6파일/UID lock/출력물 watched 밖/regression/default no-op/scan/quarantine/key literal 0/active=false) → FF push → OWNER `/gemini review` 1회 → CI GREEN + fresh unresolved 0 → **MERGE_READY_CANDIDATE** 보고 / 새 High 시 회장 보고. merge 회장 승인 전 금지.

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "deploy/systemd/anu-pickup.path"
    - "deploy/systemd/anu-pickup.service"
    - "scripts/anu_pickup_entrypoint.sh"
    - "dispatch/anu_pickup_driver.py"
    - "tests/regression/test_anu_pickup_driver_2721.py"
    - "docs/p0b_driver_runbook_260601.md"
    - "memory/events/task-2721+1.done"
    - "memory/reports/task-2721.md"
  forbidden_paths:
    - "scripts/finish-task.sh"
    - "dispatch/anu_result_pickup_runner.py"
    - "dispatch/anu_owned_callback_enforcement.py"
    - ".github/**"
  commands:
    - "pytest"
    - "python3 -m pytest"
    - "python3 -m py_compile"
  merge_policy: "none"
  ttl_hours: 48
```

## ★ dispatch 템플릿 G3(PR/머지) 무시. finalize 로컬 commit only. finish-task --action pr/systemctl/설치 일체 금지.

## goal_assertions (auto-generated)
- `python3 -m pytest tests/regression/test_anu_pickup_driver_2721.py -q`
- `python3 -c "import sys; s=open('scripts/anu_pickup_entrypoint.sh').read(); sys.exit(0 if ('UID' in s and '/tmp/anu-pickup.driver.lock' not in s.replace('XDG_RUNTIME_DIR','')) else 1)"`