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

> 본 보고서는 micro-fix 전용. 누적 내역은 `memory/reports/task-2721.md` 하단 `# task-2721+1 micro-fix` 섹션에도 추가됨.

## Situation
PR #167(head `1971d1af`) 독립 파서 기준 fresh HIGH 2건이 유효 결함으로 확인됨(회장 인가 2026-06-01, Option 1). dismiss 금지, active=false 유지 조건으로 micro-fix 수행.

## Complication
- **HIGH-1**: entrypoint 가 `/tmp/anu-pickup.driver.lock` 고정 경로를 직접 사용 → 멀티유저 lock 충돌.
- **HIGH-2**: `.path` unit 이 `memory/events` 전체를 `PathModified` 감시 + driver 가 출력물(jsonl/quarantine)을 같은 디렉터리에 기록 → **피드백 루프**(driver 출력이 unit 재트리거).

## Question
PR #167 동일 6파일 범위 내에서, finish-task.sh·P0-a main 무수정·ANU key literal 0·active=false 를 유지하며 두 HIGH 를 어떻게 제거하는가?

## Answer (수정 내역)
### HIGH-1 — lock 경로 UID 분리 (`scripts/anu_pickup_entrypoint.sh`)
- `PICKUP_UID="$(id -u)"` + `LOCK="${XDG_RUNTIME_DIR:-/tmp}/anu-pickup-${PICKUP_UID}.driver.lock"` 로 변경.
- `/tmp/anu-pickup.driver.lock` 고정 문자열 제거 → 사용자별 충돌 방지.
- driver-level `flock -n 9` single-flight 유지. pickup_once 내부 lock 재도입 없음(lock-free 유지).

### HIGH-2 — watcher 피드백 루프 제거
- `dispatch/anu_pickup_driver.py`: driver 출력 경로 상수를 `memory/events` 밖으로 분리
  - `QUARANTINE_DIR_REL = "memory/p0b_state/quarantine"` (이전 `memory/events/quarantine`)
  - `EVIDENCE_JSONL_REL = "memory/p0b_state/driver_runs.jsonl"` (이전 `memory/events/p0b_driver_runs.jsonl`)
  - `EVENTS_DIR_REL = "memory/events"` (스캔 **입력** 디렉터리)는 불변. `_dedupe_hit` ledger(읽기 전용 입력)도 불변.
- `deploy/systemd/anu-pickup.path`: `PathModified=%h/workspace/memory/events` → `PathExistsGlob=%h/workspace/memory/events/task-*.result.json` (입력 전용 glob).
- `docs/p0b_driver_runbook_260601.md`: 데이터 흐름/evidence 경로 갱신 + `## 8. micro-fix 이력` 섹션 추가.

### active=false 유지
- installed=false / wired=false / active=false. 활성화(systemctl/flag/pilot/merge) 일체 미수행.

## 변경 파일 (vs PR#167 base 1971d1af — 5 changed, 54 insertions / 9 deletions)
1. `scripts/anu_pickup_entrypoint.sh` (lock UID)
2. `dispatch/anu_pickup_driver.py` (출력 경로 상수)
3. `deploy/systemd/anu-pickup.path` (input-only glob)
4. `docs/p0b_driver_runbook_260601.md` (런북)
5. `tests/regression/test_anu_pickup_driver_2721.py` (regression 11→13)
- `deploy/systemd/anu-pickup.service`: 변경 불필요(무수정). finish-task.sh / P0-a main 무수정.
- `git diff --name-only origin/main` = 6파일(PR#167 동일).

## 테스트 결과
- `python3 -m pytest tests/regression/test_anu_pickup_driver_2721.py -q` → **13 passed** (기존 11 + 신규 2).
  - 신규 `test_entrypoint_lock_path_uid_isolated`: lock 경로 UID 포함 + 고정 경로 미사용 + flock 유지.
  - 신규 `test_driver_outputs_outside_watched_dir`: quarantine/evidence 상수가 `memory/p0b_state` (watched 밖).
  - 갱신 `test_quarantine_size0` / `test_scan_once_evidence_jsonl`: 출력물이 `memory/events` 밖임을 단언.
- `python3 -m py_compile dispatch/anu_pickup_driver.py` → PYCOMPILE_OK
- `bash -n scripts/anu_pickup_entrypoint.sh` → BASH_SYNTAX_OK
- goal_assertion(UID 포함 & `/tmp/anu-pickup.driver.lock` 미사용) → ASSERT_PASS

## L1 스모크테스트 결과
- 서버 재시작: 해당없음(systemd path driver, default DISABLED — 실설치/기동 금지 대상)
- API 응답 확인: 해당없음(HTTP API 아님)
- 스크린샷: 해당없음(프론트엔드 아님)
- 실동작 확인(subprocess) — **실제 실행 + 통과**:
  - L1-a: `bash scripts/anu_pickup_entrypoint.sh` (activation flag 부재) → **exit 0 (no-op)** 정상.
  - L1-b: `drv.scan_once()` 실호출(mock pickup/verify, 실제 wake 0, activation enabled, temp root):
    - verdict `WAKE_BUILT`, evidence 가 `memory/p0b_state/driver_runs.jsonl`(watched **밖**)에 기록됨 확인.
    - `memory/events/p0b_driver_runs.jsonl`(watched 안) 미생성 확인 → **피드백 루프 제거 실증**.
    - quarantine 경로 `memory/p0b_state/quarantine` (watched 밖) 확인.
    - evidence 내 ANU key literal 미노출(False) 확인.

## 검증 (finalize 전)
- finish-task.sh 변경 0. ANU key literal **net-new 0**(vs 1971d1af `git diff` 의 `+c119085` 라인 0). 연속 literal `c119085addb0f8b7` 미존재.
  - 테스트의 분할 문자열(`"c119085"+"addb0f8b7"`)은 PR#167 기존 anti-pattern(absence 검증용)으로 net-new 아님.
- driver 출력 경로 `memory/events` 밖(grep 확인). `/tmp/anu-pickup.driver.lock` 고정 0.

## 발견 이슈 및 해결
- Pyright 경고(`argv` 미사용 @main, test의 `calls` 속성/`dispatch` import 미해결)는 PR#167 기존 패턴으로 본 micro-fix 회귀 아님(런타임 13 PASS). 범위 외로 유지.
- 6파일 중 `anu-pickup.service` 는 변경 불필요 → 무수정(범위 준수).

## 머지 판단
- **머지 필요**: No (본 봇 수행 금지 — ANU governance)
- **브랜치**: task/task-2721-dev1 (head `98cb8a2a`, base `1971d1af`)
- **워크트리 경로**: /home/jay/workspace/.worktrees/task-2721-dev1
- **머지 의견**: 로컬 commit only. push/PR/merge/설치/활성화 금지(회장 인가 verbatim). ANU 독립 재검증(6파일/UID lock/출력물 watched 밖/regression 13 PASS/default no-op/scan 한정/quarantine/key literal 0/active=false) → FF push → OWNER `/gemini review` 1회 → CI GREEN + fresh unresolved 0 시 **MERGE_READY_CANDIDATE** 보고. merge 는 회장 승인 전 금지.

## 모델 사용 기록
- 헤르메스(팀장, Opus): 설계/분배/통합/검증/L1/보고 (직접 코딩 0 — 위임 원칙 준수)
- 불칸(백엔드, **sonnet** via general-purpose): entrypoint/driver/.path/runbook 수정
- 아르고스(테스터, **sonnet** via general-purpose): regression 갱신 2 + 신규 2
- haiku 미사용 (보안·계약 민감 작업 → sonnet 이상 적용)

## 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 회장 승인 전 금지.
