# task-2717+1 — Phase 1 pre-PR 보정 report (dev1, 헤르메스)

- **분류**: Phase 1 (TRUST 제거/탐지) pre-PR 보정. **7f644a1a 폐기 아님 — 유지+보정.**
- **worktree**: `/home/jay/workspace/.worktrees/task-2717-dev1`
- **branch**: `task/task-2717-anu-owned-callback-enforcement`
- **base(origin/main)**: `2321dd8b`
- **parent**: `7f644a1a` (원 ANU_OWNED_CALLBACK_ENFORCEMENT)
- **new commit**: `7f6b0b5527539a0dab64160716e993a733bc5f13`
- **PR #162**: 미접촉 · 새 worktree/브랜치: 생성 0 · **push: 0 (로컬 commit only)**
- **허용 파일 2개만 변경**: `dispatch/anu_owned_callback_enforcement.py` · `tests/regression/test_anu_owned_callback_enforcement_2717.py`

---

## 보정 3건 + fire-path gating

### A. 실제 ANU key literal 전부 제거
- 모듈 docstring(self-collector incident 설명문) 의 `"ANU key c119085addb0f8b7 사용"` → `"ANU key <ANU_KEY_REDACTED> 사용"`.
- 테스트: line 51 주석의 literal 제거(`# 독립 ANU key (import 상수 — 실 literal 비노출)`), spoof envelope note 의 literal → `f"ANU key {ANU_KEY_PLACEHOLDER} 사용"` (`ANU_KEY_PLACEHOLDER = "<ANU_KEY_REDACTED>"`).
- **import 상수 `ANU_KEY`(= `callback_owner_enforcer.ANU_KEY_2553`) 사용은 유지** — literal 문자열만 제거.
- 검증: `grep c119085addb0f8b7` 2파일 = **0** (module 0 / test 0).

### B. status enum 보강 (상태기계 명확화)
- **`NO_RESULT_JSON`** (`CLS_NO_RESULT_JSON`): executor 가 result JSON **자체를 미작성**(runner pickup 시 파일 부재). `anu_runner_pickup_and_fire` pickup step 의 file-부재 branch 에 분류 부여 — parse 실패/비-object 와 구분.
- **`PENDING_OWNER_PROOF`** (`VERDICT_PENDING_OWNER_PROOF` / `CLS_PENDING_OWNER_PROOF` / owner outcome `OWNER_PENDING`): owner proof **미확정**(cron-history 결정적 답 없음 = probe 예외 / garbled 응답 / 미상 status) → **재시도 가능**. `verify_collector_authoritative` 에 전용 분기 추가.
- ★ **result 없음(NO_RESULT_JSON)** 과 **owner 미확정(PENDING_OWNER_PROOF)** 은 **서로 다른 상태**로 분리 (test_8 / test_9 로 고정).
- fail-closed 분리: 명시적 비-access-denied error 응답은 기존 `OWNER_QUERY_FAILED → NON_AUTHORITATIVE`(fail-closed) 유지 — PENDING(재시도 가능)과 명시적으로 구분.
- 기존 `AUTHORITATIVE` / `QUARANTINED`(SELF_COLLECTOR_QUARANTINE) / `NON_AUTHORITATIVE` / `REJECTED` 와 **충돌 없이** 추가.

### C. spoof → QUARANTINE regression 강화
- spoof envelope: `collector_role=ANU` / `self_key_used=false` / `owner_key=ANU` **주장**하나, actual owner proof(ANU key 로 cron-history 조회)는 self-key 소유 schedule → **access denied**.
- 반드시 출력 3종 동시 고정: `SELF_COLLECTOR_QUARANTINE` · `usable_for_auto_merge=false` · `work_preserved=true`.
- envelope claim 은 `envelope_claims` 로 **기록만** 되고, 판정은 `owner_resolution.outcome == NOT_ANU` 가 결정함을 명시적으로 assert.
- test_1 강화 + 신규 test_7 추가 (test_6 기존 비차단 보존 검증과 함께 3중).

### fire 경로 제한 (Phase 1)
- Phase 1 에서 cokacdir cron 을 정상 fire/closeout 실행 경로로 **전제하지 않음**.
- `RunnerResult.dry_run=true` / `fire_path=NOT_ACTIVATED` — runner 는 argv(데이터)만 surface, 자가발사 0.
- 신규 게이트 `fire_callback_request(runner_result, activate=)`: `activate=False → NOT_ACTIVATED`, `activate=True → PHASE2_REQUIRED`. **두 경우 모두 `fired=false`** (Phase 1 실 fire 0).
- 허용: read-only `--cron-history` 조회(`RealCokacdirCronHistoryProbe`) + ANU-owned argv build dry-run + NOT_ACTIVATED 차단.

---

## 검증 (전부 PASS)

- 실제 ANU key literal: `grep c119085addb0f8b7` 2파일 = **0**.
- `NO_RESULT_JSON` / `PENDING_OWNER_PROOF` 동작: test_8 / test_9 PASS (서로 다른 상태 + fail-closed 와 구분).
- spoof→QUARANTINE: test_1 / test_6 / test_7 PASS.
- result JSON schema · 멱등 lock: test_11 PASS (schema 필드 + atomic `os.replace` 멱등 write).
- regression(대상 파일): **12 passed** (기존 7 + 신규 5).
- `git diff --name-only origin/main...HEAD` = **2** (expected files only) · forbidden 0 · **Phase2 혼입 0** · **CI workflow 0**.

### regression 디렉터리 전체
`tests/regression/` = **1548 passed, 11 skipped, 4 failed**.
- 4 failed 는 모두 `finish-task.sh` stash audit 검사 (`test_finish_task_stash_audit_existence_guard.py`, `test_stash_origin_audit_compat.py`) — **본 task 2파일과 무관**(task-2717/module 미참조). 보정 전후 동일, **본 보정이 도입한 실패 0** (pre-existing).

---

## Phase 2 혼입 금지 (전부 제외 확인)
OS-level pickup · systemd/inotify/crontab 설치 · executor cron 차단 hook · completion_contract 자동주입 · ANU key 봉인 배포 · 실 fire/closeout 자동화 — **전부 미포함** (added-line 토큰 스캔 0).

## commit guard 처리
pre-commit hook 이 `.tasks/locks/task-2717.lock` 을 요구하나, 원작업 완료 후 stale-cleanup 으로 lock 이 제거된 상태였다. 상태기계 전이/PR #162 부수효과를 피하기 위해 lock 재생성 대신 hook 공식 escape hatch 인 `TASKCTL_BYPASS=1` + 사유 기록을 사용(단일 task·2파일·branch 일치 commit). evidence: `.tasks/evidence/task-2717/bypass-2026-05-30T18:20:25Z.json`.

## push / 자가발사
- **push 금지** 준수 — 로컬 commit 까지만 (branch ahead 2, origin 미반영). push/PR 생성 0. push 는 ANU 재검증 PASS + 회장 인가 후.
- **callback schedule 자가발사 0** (self-collector 패턴 차단) — 본 task 는 result JSON + report 작성만 수행.

## 완료 신호
`memory/events/task-2717+1.result.json` (new_commit_sha / key_literal_count=0 / new_statuses / spoof_quarantine_test / fire_path_gated / expected_files / regression_result).
