# task-2721+3 — PR #167 P0-b HIGH fix: result.json write race(부분 JSON 즉시 quarantine) 방어

## 회장 인가 (2026-06-02, Option 1 — 새 HIGH 1건 명시 승인)
PR #167(head `a905fc41`) fresh HIGH 1건 = 유효 결함, dismiss 금지.
- **HIGH(race)**: systemd path watcher 가 writer **flush 완료 전** `task-*.result.json` 생성을 감지 → driver 가 **부분 JSON 을 즉시 quarantine** → 데이터 손실 + callback 누락. P0-b OS-level pickup 경로 핵심 안정성 문제.
★ 이번이 새 HIGH 명시 승인. 이 후 또 새 HIGH 나오면 추가 자동 fix 금지 → CHAIR_REQUIRED.

## worktree
- `/home/jay/workspace/.worktrees/task-2721-dev1` (branch `task/task-2721-dev1`, head `a905fc41`)에서 **이어서**. 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 writer atomic 화는 **P0-b+1 후속 유지**). P0-a main 무수정.

## 수정 — write race 방어 (readiness grace window)
1. ★ **부분 JSON parse 실패를 즉시 quarantine 하지 않는다.** writer 미완 가능성을 먼저 배제.
2. **readiness 판정**: `task-*.result.json` 이 너무 최근 생성/수정(예: mtime 이 now - STABLE_SEC 이내)이면 **`NOT_READY`/`DEFER`** 로 처리 — **wake/quarantine 모두 금지**(다음 트리거/재시도에서 재평가).
   - 단순 sleep 만 넣지 말 것. 권장: **size/mtime 안정성 검사**(짧은 간격 2회 stat → size·mtime 불변 시 ready) 또는 **짧은 retry window**(예: 총 ≤2s, N회 재시도) 중 택1/조합.
   - STABLE_SEC/retry 파라미터는 모듈 상수로(테스트에서 주입 가능하게).
3. **grace window 이후에도** size0 / parse fail / schema fail 이면 **그때 quarantine**(기존 6조건 유지, 단 readiness 통과 후 적용).
4. **null byte 방어**: result 내용에 null byte(`\x00`) 등 truncation 흔적이 있으면 grace 내 DEFER, grace 후 잔존 시 quarantine(부분 write 잔재 차단).
5. driver 안정성에 직접 관련된 잔여 medium 중 expected_files 내부 작은 보강이면 함께 처리 가능.
6. ★ 성능 medium / fsync 제거처럼 **본질 안정성과 무관한 항목은 넣지 말 것**(필요 시 evidence-based resolve 후보로 분리 — 코드 변경 0).

## verdict enum 추가
- `NOOP_NOT_READY`(또는 DEFER) 추가: readiness 미충족 → wake 0 / quarantine 0 / evidence 기록. 다음 평가에서 재시도.

## regression (추가/갱신)
- 기존 22 PASS 유지/증가.
- ★ **부분 JSON + 최근 mtime** result.json → **즉시 quarantine 안 됨**(NOOP_NOT_READY/DEFER) + pickup_once 미호출(mock) + quarantine 미발생.
- ★ **오래된 invalid JSON**(mtime 충분히 과거) → grace 후 **quarantine 됨**.
- size/mtime 안정 후 정상 result.json → 6조건 통과 → pickup_once(mock) WAKE_BUILT.
- null byte 부분 write → grace 내 DEFER, grace 후 잔존 시 quarantine.
- default disabled no-op / scan 한정 / 출력물 watched 밖 / 기존 path-traversal·fail-safe 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(22→증가).
- `git diff --name-only origin/main` = 6파일. finish-task.sh 0. ANU key net-new 0.
- readiness(size/mtime 안정 또는 retry window) 로직 존재. NOT_READY/DEFER 분기 존재. 단순 무한 sleep 없음.

## 금지 (회장 verbatim)
- finish-task.sh 수정 금지(writer atomic = P0-b+1 유지) · systemctl enable/start/daemon-reload 금지 · unit 설치 금지 · activation flag 생성 금지.
- 실 pickup/wake/ANU key wake 실행 금지 · merge 금지 · force push/rebase/admin override 금지.
- ANU key literal 노출 0 · pickup_once lock 재도입 금지 · P0-a main 무수정 · expected_files 밖 수정 금지.
- active=false / installed=false / wired=false 유지. capability matrix 과장 금지.
- ★ 새 HIGH 또 발생 / expected_files 밖 / 권한확장 / forbidden / 동일 blocker 반복 시 → 추가 fix 금지, **CHAIR_REQUIRED 보고**.

## finalize (로컬 commit 까지만)
1. fix → regression PASS → `git add` 6파일 → 로컬 commit. **push/PR/merge 금지(ANU 수행)**.
2. `memory/reports/task-2721.md` 에 HIGH race fix 내역(readiness grace window / NOT_READY-DEFER / null byte 방어) 추가.
3. `memory/events/task-2721+3.done` 생성. ANU key(c119085, sealed) callback. ★ ANU key literal 노출 0.

## ANU 후속 (봇 아님 — governance)
독립 재검증(6파일/readiness DEFER/오래된 invalid quarantine/regression/key 0/active=false) → FF push → OWNER `/gemini review` 1회 → CI GREEN + fresh unresolved 0 → **MERGE_READY_CANDIDATE** 보고 / 새 HIGH·동일 blocker 반복 시 CHAIR_REQUIRED. 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+3.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('dispatch/anu_pickup_driver.py').read(); sys.exit(0 if ('NOT_READY' in s or 'DEFER' in s) and 'mtime' in s else 1)"`