# task-2553 — Fine-grained OWNER PAT trigger-only 모듈 구현 (Phase 0~3)

**레벨**: Lv.4 (security/control-plane, ANU v2 5 모듈 통합)
**트랙**: A (control-plane, GEMINI_EXTERNAL_TRIGGER_GAP 자동 해소)
**팀**: dev5 마르둑 (ANU v2 merge_queue_executor / post_merge_smoke_runner 작성자)
**선행**: task-2552 (OWNER trigger 자동화 사전조사 PASS) → 회장 dec_1 doctrine 예외 조건부 승인

---

## 본질 (회장 §명시 2026-05-11 dec_1 승인)

회장 결정: **Fine-grained OWNER PAT trigger-only doctrine 예외 조건부 승인**.

**OWNER PAT 일반 사용 허용 X** — 오직 GitHub Gemini App을 깨우기 위한 `/gemini review` 댓글 작성에만 한정.

### 승인 근거 (회장 §명시 1:1, 7항목)

1. bot 댓글 trigger 0/5 (0%) 미작동 실증
2. OWNER 댓글 trigger 10/10 (100%) 작동 실증
3. 공식 docs 미명문 + 실증 trigger gap 확정
4. comment-only fine-grained PAT 구성 가능
5. Issues:write 단독 권한으로 merge/approve/close/reopen/push 차단 가능
6. 기존 BOT_GITHUB_TOKEN merge doctrine 유지
7. merge/approve/push/close/reopen에 OWNER PAT 사용 계속 금지

---

## 허용 범위 (회장 §명시 1:1, 6항목)

`/gemini review` 댓글 작성은 **다음 6 조건 모두 만족 시에만**:

1. comment body 정확히 `/gemini review` only
2. **queue-head PR only** (merge queue의 head)
3. current head SHA **확정 이후** only
4. Gemini evidence가 current head에 **없을 때** only
5. PR/head당 **1회 only** (dedupe)
6. `owner_trigger_decision.json`이 PASS일 때 only

---

## 금지 15건 (회장 §명시 1:1)

1. ❌ OWNER PAT으로 merge
2. ❌ OWNER PAT으로 approve
3. ❌ OWNER PAT으로 push/commit
4. ❌ OWNER PAT으로 close/reopen
5. ❌ OWNER PAT으로 branch update
6. ❌ OWNER PAT으로 issue/PR comment 일반 작성
7. ❌ `/gemini review` 외 comment 작성
8. ❌ 같은 PR/head 반복 trigger
9. ❌ queue-head가 아닌 PR trigger
10. ❌ update-branch 전 trigger
11. ❌ current head 미확정 상태 trigger
12. ❌ token value 로그 출력
13. ❌ token을 report/md/audit에 평문 기록
14. ❌ default GH_TOKEN fallback
15. ❌ BOT_GITHUB_TOKEN 대신 OWNER PAT 사용 (merge 등)

---

## 필수 구현 조건 12항목 (회장 §명시 1:1)

1. fine-grained PAT scope는 comment trigger에 필요한 **최소 권한**으로 제한 (Issues:write 단독, 다른 권한 0)
2. token은 **별도 secret**으로 저장 (`.env.keys` 등 BOT_GITHUB_TOKEN과 분리)
3. token 값은 **절대 출력/로그/박제 X**
4. audit에는 **token hash 또는 token_present 여부만** 기록
5. trigger 전 **`owner_trigger_decision.json`** 생성 (PASS/REJECT 판정 박제)
6. trigger 후 **`owner_trigger_audit.jsonl`** append-only 기록 (PR / head / ts / actor / outcome)
7. nudge dedupe는 **PR/head 단위** 적용
8. update-branch 이후 새 head 생기면 **기존 trigger는 stale**로 간주
9. **새 head에 대해서만 새 trigger 가능**
10. trigger 성공 후 **Gemini evidence commit_id == current_head 검증**
11. evidence 도착 후 merge는 **반드시 BOT_GITHUB_TOKEN으로만** 수행
12. **mergedBy = app/jeon-jonghyuk-taskctl-bot** 강제

---

## Phase 0~3 구현 (회장 §명시 1:1)

### Phase 0 — Secret 인프라
- secret 이름 / 저장 위치 / 권한 경계 정의 (예: `OWNER_GEMINI_TRIGGER_PAT`, `.env.keys` 별도 entry)
- token loading **fail-fast** (token 누락 시 즉시 ESCALATED, fallback X)
- token **redaction guard** (logger filter, str.replace, 모든 출력 경로 cover)

### Phase 1 — Decision schema
- `owner_trigger_decision.json` schema 구현
  - fields: `pr_number, head_sha, decision (PASS/REJECT), reason, gemini_evidence_state, queue_position, dedupe_key, ts`
- nudge dedupe by PR/head (sqlite or jsonl audit log lookup)
- queue-head / current-head 검증 (merge_queue_executor 상태 조회)

### Phase 2 — Trigger-only comment writer
- 신규 모듈: `anu_v2/owner_trigger_pat.py` (단일 책임)
- 허용 comment body **정확히 `/gemini review`만** (다른 body fail-fast)
- 다른 endpoint 호출 차단 (issue close, PR merge 등 API 호출 0)
- audit log append-only 기록

### Phase 3 — merge_queue_executor 연동
- `anu_v2/merge_queue_executor.py` 통합: queue-head PR에서 Gemini evidence missing 감지 → owner_trigger_pat 호출
- Gemini fresh evidence 감지 (commit_id == current_head)
- evidence 도착 후 **BOT_GITHUB_TOKEN** squash merge → smoke → reconcile → done.acked → merge-done → lineage 자동 진행
- self-resume 구현 (OWNER manual 개입 0)

---

## expected_files (자율 산정, 가이드)

**예상 expected_files (8-10개)**:

1. `anu_v2/owner_trigger_pat.py` (신규, trigger-only PAT loader + comment writer)
2. `anu_v2/merge_queue_executor.py` (Phase 3 통합)
3. `anu_v2/tests/test_owner_trigger_pat_phase0_2553.py` (token loading + redaction)
4. `anu_v2/tests/test_owner_trigger_pat_phase1_2553.py` (decision schema + dedupe)
5. `anu_v2/tests/test_owner_trigger_pat_phase2_2553.py` (comment writer fail-fast)
6. `anu_v2/tests/test_owner_trigger_pat_phase3_integration_2553.py` (merge_queue_executor 연동)
7. `tests/regression/test_bot_trigger_fail_2553.py` (bot trigger 0/5 fixture 재현)
8. `tests/regression/test_owner_trigger_success_2553.py` (OWNER trigger 10/10 fixture 재현)
9. `tests/regression/test_owner_trigger_security_boundaries_2553.py` (merge/approve/close/push 차단 어설션)
10. `memory/reports/task-2553.md` (보고서)

→ 실제 expected_files는 dispatch_decision에서 자율 산정 + Phase별 분리.

---

## forbidden paths

- 다른 task markers 변경 X
- `.github/workflows/` 변경 X (Gemini App 설정 변경 X)
- `dispatch/__init__.py` Phase 3 외 변경 X
- `prompts/team_prompts.py` 변경 X
- `dashboard/` 변경 X
- `scripts/ci.sh` 변경 X
- 다른 anu_v2 모듈 (post_merge_smoke_runner, replacement_pr_runner, auto_gemini_triage, critical_escalation_reporter) Phase 3 통합 외 변경 X
- production OWNER PAT 실제 생성 X (test fixture only, 회장이 별도 secret 주입)
- task-2549.* / task-2550.* / task-2551.* / task-2552.* markers 변경 X
- `.worktrees/` 변경 X
- POC 영역 변경 X

---

## test fixture (회장 §명시 완료 기준 5항목)

1. **bot trigger fail** — bot token 댓글이 Gemini auto trigger 작동 안 함 어설션
2. **owner trigger success** — OWNER PAT 댓글이 Gemini fresh review 도착 시뮬레이션
3. **duplicate nudge blocked** — 같은 PR/head 2회 trigger 시 2회차 fail-fast
4. **update-branch stale reset** — 새 head 생기면 기존 trigger 무효, 새 trigger 가능
5. **non-queue-head blocked** — queue-head 아닌 PR에 trigger 시 fail-fast

회귀 95% 이상 coverage 권장.

---

## 4-layer gate (Lv.4 강제)

- **G1 Codex 사전 검증** (`.codex-gate`) 필수
- **G2 마아트 + 로키** (`.qc-result`) — Lv.4 security 강제 (보안 경계 적대적 평가 핵심)
- **G3 independent_verifier** (`.g3-fail` or `.g3_pass`) 필수, SCQA 패턴
- **G4 Pre-PR Gemini CLI Gate** — task-2548 Task A PASS 박제, Task B 구현 보류 중 → 본 task G4 미적용 가능 (회장 §명시 finalize 14단계 그대로 적용)

---

## 봇 직접 행동 8항목 + finalize 14단계 (★★★ 박제)

1. **BOT_TOKEN_RUNTIME_RESOLUTION_STEP0** 4-step (token refresh + .env.keys export + fail-fast + identity)
2. **OWNER_GEMINI_TRIGGER_PAT 별도 secret** 정의 (token value는 회장 별도 주입 단계, 봇은 fixture에 placeholder만 사용)
3. **Codex G1 gate** (Lv.4 강제) — 설계 사전 검증
4. **clean worktree** (origin/main 기반)
5. **expected_files 자율 산정** + dispatch_decision 명시
6. **구현 + G2 (마아트+로키) + G3 + Lv.4 sanitize gate**
7. **PR 생성 + Gemini fresh + unresolved 0 + CI all SUCCESS + mergeStateStatus CLEAN**
8. **BOT squash merge** + post_merge_smoke + reconcile + done.acked + merge-done + lineage

---

## 완료 기준 7항목 (회장 §명시 1:1)

1. OWNER PAT은 `/gemini review` 댓글 작성에만 사용됨 (다른 endpoint 호출 0)
2. merge/approve/push/close/reopen 권한 사용 0 (모두 BOT_GITHUB_TOKEN)
3. queue-head/current-head 아닌 PR trigger 0
4. 같은 PR/head 중복 trigger 0
5. token value log 0 (audit log에 token_present boolean만)
6. BOT merge identity 유지 (mergedBy = `app/jeon-jonghyuk-taskctl-bot`)
7. test fixture 5건 모두 PASS (bot trigger fail / owner trigger success / duplicate nudge blocked / update-branch stale reset / non-queue-head blocked)

---

## 보고

MERGED 또는 ESCALATED만.

### MERGED 보고 필수
- PR number / mergedAt / mergedBy = `app/jeon-jonghyuk-taskctl-bot`
- effective diff == corrected expected_files
- forbidden path 0
- Phase 0~3 모두 구현 + 5 fixture PASS
- token value log 0 (audit 검증)
- pyright 0
- smoke + reconcile evidence 존재
- post-merge worktree 보존 (task-2550 worktree_cleanup 미적용, 회장 별도 승인 후만)

### ESCALATED 보고 필수
- Critical 7 번호
- exact blocking gate (Phase 0/1/2/3 어디서 fail)
- token value 노출 여부 (반드시 0)
- 보안 경계 위반 여부 (G2 로키 적대적 평가 결과)
- 다음 owner action

ESCALATED 매핑:
- Phase 0 secret loading fail → #6 SECRET_LOADING_FAIL
- Phase 1 dedupe schema fail → #2 EFFECTIVE_DIFF_FAIL
- Phase 2 comment body 비허용 → #4 BLOCK_OVERRIDE (보안 경계 위반)
- Phase 3 merge_queue_executor 통합 fail → #6 INTEGRATION_FAIL
- token value 노출 → #4 TOKEN_REDACTION_FAIL (★ 최우선 차단)
- G2 로키 적대적 평가 FAIL → 보안 결함

---

## 최종 원칙

ANU v2 자기참조 control-plane Lv.4 task. **OWNER PAT은 단 1개 함수 (`/gemini review` comment writer)에서만 사용**. 모든 다른 권한은 BOT_GITHUB_TOKEN. 보안 경계 명확.

본 task MERGED 후 자동 GEMINI_EXTERNAL_TRIGGER_GAP 해소 → 회장 수동 trigger 부담 0 (PR/head당 1회 자동 nudge) → 100% green path 자동 머지 doctrine 실현.

회장 §명시 12 필수 구현 조건 + 15 금지 + 6 허용 범위 + 7 승인 근거 + Phase 0~3 + 5 fixture 1:1 강제.

★ task-2548 Task A (G4 사전조사) + task-2552 (OWNER trigger 사전조사) doctrine 일관 적용. task-2549/2550/2551 expected_files overlap 0이라 병렬 진행 안전.
---

## allowed_resources

```yaml
allowed_resources:
  paths:
    - "anu_v2/owner_trigger_pat.py"
    - "anu_v2/merge_queue_executor.py"
    - "anu_v2/tests/test_owner_trigger_pat_phase0_2553.py"
    - "anu_v2/tests/test_owner_trigger_pat_phase1_2553.py"
    - "anu_v2/tests/test_owner_trigger_pat_phase2_2553.py"
    - "anu_v2/tests/test_owner_trigger_pat_phase3_integration_2553.py"
    - "tests/regression/test_bot_trigger_fail_2553.py"
    - "tests/regression/test_owner_trigger_success_2553.py"
    - "tests/regression/test_owner_trigger_security_boundaries_2553.py"
    - "memory/reports/task-2553.md"
    - "memory/plans/tasks/task-2553/**"
    - "memory/events/task-2553.*"
    - "memory/tasks/task-2553.md"
  forbidden_paths:
    - ".github/workflows/**"
    - "dispatch/__init__.py"
    - "prompts/team_prompts.py"
    - "dashboard/**"
    - "scripts/ci.sh"
    - ".worktrees/**"
    - "anu_v2/post_merge_smoke_runner.py"
    - "anu_v2/replacement_pr_runner.py"
    - "anu_v2/auto_gemini_triage.py"
    - "memory/tasks/task-2549*.md"
    - "memory/tasks/task-2550*.md"
    - "memory/tasks/task-2551*.md"
    - "memory/tasks/task-2552*.md"
```
