# task-2468 — Phase C: 자동 PR Lifecycle 신뢰성 코드 구현 (Code-First, NOT Docs)

- 작업 유형: **code-implementation** (회장 명시 "문서화 task 아님")
- 작업 레벨: **Lv.4 critical**
- 위임팀: **dev6-team (페룬, opus)**
- Track: **dev_workspace** (시스템 거버넌스, drink your own champagne)
- 우선순위: **★★★ P0 — task-2467+3 silent-corruption 결함 차단**
- 일시: 2026-05-06
- 선행: task-2467+3 MERGED (8d667080) ✅
- 후행: task-2469 (Phase D — Penetration tests)

## ⚠️ 본 task의 본질 — 회장 명시

> "이번 task-2468의 산출물은 일반 MD 문서/스펙 보강이 아니라, **자동 PR lifecycle을 실제 코드로 강제하는 구현 + 테스트 + 증거 로그**다. 문서화는 보조 산출물일 뿐이며, 완료 조건은 반드시 **실행 가능한 코드/테스트/게이트 통과**로 판단한다."

> "구현 없는 MD 보강은 reject 처리한다."

→ **코드 구현이 본질, MD/spec/보고서는 evidence**.

## 0. 배경 — task-2467+3에서 발견된 4대 결함

본 task의 목표 = **task-2467+3에서 드러난 자동 merge 시스템 신뢰성 결함을 코드 레벨에서 차단**.

| # | 결함 | 증거 |
|---|------|------|
| 1 | `.done` + `.g3-fail` 동시 존재 (시스템 일관성 깨짐) | `memory/events/task-2467+3.done` + `task-2467+3.g3-fail` |
| 2 | Gemini 시각 priority(High 3건) ≠ gate `high_severity_hits`(0건) 불일치 | `task-2467+3.g3-fail` "보고서 High=0건, 실제 High=3건" |
| 3 | approver=`JonghyukJeon` (회장 본인 계정)이 Green Path 자동 승인으로 인정됨 | `task-2467+3.md` §6 |
| 4 | `done` 발행 전 G3 PASS evidence 재검증 누락 | g3-fail 박제됐으나 .done 발행됨 |

## 1. P0 — 코드 자동화 필수 구현 (10건)

### P0-1. `.g3-fail` 존재 시 `.done` 발행 금지 + conflict 분류
- **구현 위치**: `scripts/taskctl.py` done 단계 + `scripts/finish-task.sh` + `scripts/worktree_manager.py`
- 동일 task_id의 `.g3-fail` 또는 verifier fail marker 검사 → 존재 시 `.done` 작성 차단 + hard fail
- 이미 `.done`이 존재하더라도 `.g3-fail`이 생성되면 **conflict 상태**로 분류 + 후속 ack/merge 차단
- 테스트 (P1-A, P1-B): `.g3-fail` + `.done` 동시 fail / conflict 판정

### P0-2. done 발행 전 G3 PASS 재검증
- done 단계 진입 직전 G3 verifier 결과 다시 read
- g3 PASS evidence 없으면 done 발행 금지
- **stale PASS / 다른 task_id PASS / 이전 PR PASS 재사용 금지** (task_id + PR + commit SHA 매칭 강제)
- 테스트 (P1-N): PASS 없음 / stale / 다른 task_id 모두 done 차단

### P0-3. Gemini High 판정 표준화 (가장 중요)
- 시각 priority + gate `high_severity_hits` 단일 parser로 통합
- 정규화 대상:
  - emoji (🔴 / 🚨 / ⚠️ 등 priority 마커)
  - heading (`## High`, `### Critical`)
  - severity label (`severity: high`, `priority: critical`)
  - keyword (`BLOCKING` / `CRITICAL` / `MUST FIX`)
  - "High" / "Medium" / "Low" 표현
- High 1건 이상 → auto approve / auto merge 차단
- Medium / Low → 정책 분리 (warning or non-blocking)
- 테스트 (P1-C, P1-D): High 3건 fixture → `high_severity_hits=3` 산출

### P0-4. auto-approve / auto-merge 차단 7조건 통합
하나라도 true면 approve/merge/done **모두 차단**:
1. Gemini High > 0
2. G3 fail marker 존재
3. required check 미통과
4. hidden path audit fail
5. merge SHA 검증 실패
6. PR author allowlist 불일치
7. approver identity 불일치

### P0-5. approver identity 시스템화
- **자동 approve 인정 identity 화이트리스트**:
  - `taskctl-gate`
  - `anu-verifier`
  - configured GitHub App bot (`memory/specs/allowed_approvers.json`)
- **사람 직접 approve = "manual approval"** 별도 audit 처리, Green Path 자동 승인으로 인정 X
- approver=`JonghyukJeon` → auto approval evidence로 인정 X
- 테스트 (P1-E, P1-F): chairman approve = manual / 시스템 승인자만 auto evidence

### P0-6. merge commit SHA 검증 자동화
- done 발행 전 GitHub `merge_commit_sha` ↔ `origin/<base>` HEAD 일치 확인
- merge_commit_sha empty/null → hard fail
- **hardcoded 'main' 금지** — PR base branch 동적 조회
- 테스트 (P1-G, P1-H, P1-I): SHA 일치/불일치/null/main 외 base 모두 검증

### P0-7. state transition 엄격화
- `ALLOWED_TRANSITIONS` 코드에 명시
- forbidden transition → hard fail
- **fail → done 직접 이동 금지**
- done 이후 fail marker 생성 시 conflict 전환
- 테스트 (P1-M): fail → done 불가 / done + fail conflict

### P0-8. bypass / override audit 강제
- `TASKCTL_BYPASS=1` 사용 시 audit log 필수 (`memory/orchestration-audit/admin-override.jsonl`)
- `TASKCTL_PR_AUTHOR_OVERRIDE` 사용 시 audit log 필수
- audit 없이 사용 시 hard fail
- 운영 환경 (`PRODUCTION=1`)에서 bypass/override 기본 금지
- 테스트 (P1-J, P1-K): env override + audit 없음 → fail

### P0-9. bot author allowlist 외부 config화
- 허용 bot/app 계정 → `memory/specs/allowed_bot_accounts.json` (하드코딩 금지)
- config 누락 / 비어있음 → fail-closed
- 테스트 (P1-L): allowlist 외 author → merge 차단

### P0-10. `TASKCTL_CWD` 제거 / `--worktree` 정식화
- `TASKCTL_CWD` 임시 env 의존 제거 또는 deprecated warning
- CLI에 `--worktree <path>` 정식 인자 추가
- 내부 경로 검증은 `--worktree` 기준
- 테스트: `--worktree` 정상 / 잘못된 worktree fail

## 2. P1 — 통합 테스트 14건 (필수)

| ID | 시나리오 | 기대 결과 |
|----|----------|-----------|
| A | `.g3-fail` 존재 시 `.done` 생성 시도 | done 차단 |
| B | `.done` + `.g3-fail` 동시 존재 | conflict 판정 |
| C | Gemini High 3건 fixture | high_severity_hits=3 |
| D | Gemini High ≥ 1건 | auto-merge 차단 |
| E | approver=`JonghyukJeon` | Green Path auto-approve 인정 X |
| F | approver=`taskctl-gate` 등 시스템 승인자 | auto-approve evidence 인정 |
| G | merge_commit_sha=null/empty | done 차단 |
| H | origin/<base> HEAD ≠ merge_commit_sha | done 차단 |
| I | base branch ≠ main | 동적 검증 PASS |
| J | TASKCTL_BYPASS=1 + audit 없음 | fail |
| K | TASKCTL_PR_AUTHOR_OVERRIDE + audit 없음 | fail |
| L | allowlist 외 author | merge 차단 |
| M | fail → done transition | 금지 |
| N | g3 PASS evidence 없음 | done 발행 불가 |

테스트 위치: `tests/taskctl/test_lifecycle_guards.py` (또는 분리)

## 3. P2 — 실제 명령 경로 연결 (★ 회장 명시)

> "단순 helper 함수 추가로 끝내지 말고, **실제 운영 명령 경로**에서 해당 gate가 실행되어야 한다."

연결 대상:
- `scripts/finish-task.sh`
- `scripts/worktree_manager.py finish`
- `scripts/taskctl.py pr-open`
- `scripts/taskctl.py approve`
- `scripts/taskctl.py merge`
- `scripts/taskctl.py done`
- `scripts/g3_independent_verifier.py`
- `scripts/anu_confirm_bot/main.py` (taskctl 라우팅)

## 4. P3 — Evidence 산출 (보고서 필수 항목 10건)

완료 보고서 (`memory/reports/task-2468.md`)에 **반드시 포함**:

1. 변경 파일 목록
2. 핵심 함수/클래스명
3. 테스트 파일 목록
4. 실행한 테스트 명령
5. 테스트 PASS 로그 (raw output)
6. 실패 fixture 재현 로그
7. **task-2467+3 사례 재현 결과** (`.done` + `.g3-fail` 동시 존재 시나리오 fixture로 재현 후 본 task 코드로 차단됨 증명)
8. Green Path 자동 approve/merge dry-run 결과
9. `.g3-fail` 존재 시 `.done` 차단 로그
10. Gemini High 3건 fixture의 `high_severity_hits=3` 산출 로그

## 5. 합격 조건 (회장 명시)

전부 충족해야 합격:
1. ✅ 코드 구현 완료 (P0 10건)
2. ✅ 테스트 추가 완료 (P1 14건)
3. ✅ 전체 관련 테스트 PASS
4. ✅ 실제 명령 경로 연결 완료 (P2)
5. ✅ task-2467+3의 `.done` + `.g3-fail` 동시 존재 문제가 재현되고, **본 task 코드로 차단됨이 증명**
6. ✅ Gemini High mismatch 문제가 재현되고, 수정 후 `high_severity_hits`가 정확히 산출됨이 증명
7. ❌ 문서만 수정한 PR은 **완료로 인정하지 않음**

## 6. ESCALATED 조건

- P0 1~10 중 1건이라도 미구현 → ESCALATED
- P1 테스트 14건 중 1건이라도 FAIL → ESCALATED
- P2 명령 경로 미연결 → ESCALATED
- task-2467+3 사례 재현 실패 → ESCALATED
- Gemini High mismatch 재현 실패 → ESCALATED
- MD/spec만 수정 → ESCALATED + reject

## allowed_resources

```yaml
allowed_resources:
  paths:
    # 코드 구현
    - "scripts/taskctl.py"
    - "scripts/finish-task.sh"
    - "scripts/worktree_manager.py"
    - "scripts/g3_independent_verifier.py"
    - "scripts/anu_confirm_bot/main.py"
    - "scripts/lifecycle_guards.py"
    - "scripts/gemini_severity_parser.py"
    # 테스트
    - "tests/taskctl/**"
    - "tests/state_machine/**"
    - "tests/lifecycle_guards/**"
    # config
    - "memory/specs/allowed_bot_accounts.json"
    - "memory/specs/allowed_approvers.json"
    - "memory/orchestration-audit/admin-override.jsonl"
    # 보고서/spec (보조)
    - "memory/specs/pr-lifecycle-spec*.md"
    - "memory/specs/taskctl-state-machine-spec*.md"
    - "memory/tasks/task-2468*"
    - "memory/reports/task-2468*"
    - "memory/plans/tasks/task-2468/**"
    # CI
    - ".github/workflows/ci.yml"
  forbidden_paths:
    - "PR #29 / #30 / #31 / #32 / #33"
    - "memory/events/task-2467+3*"  # read-only (재현 fixture는 별도 sandbox)
    - "memory/reports/task-2467+3.md"
    - "task-2465* / task-2466* / task-2467*"
    - "dispatch.py"
    - "memory/organization-structure.json"
    - "bot_settings.json"
    - ".env.keys"
    - ".secrets/**"
  forbidden_actions:
    - "구현 없이 MD/spec만 수정 (회장 reject)"
    - "task-2467+3 events/reports 수정 금지 (read-only)"
    - "admin override 사용 금지"
    - "gh pr merge / gh pr create 직접 호출 금지 (taskctl 외)"
    - "git push origin main 직접 호출 금지"
    - "GEMINI_API_KEY 도입 금지"
    - "task-2469 (Phase D) 선행 금지"
  bot_authentication:
    - "BOT_GITHUB_TOKEN .env.keys에서 자동 로드 (Installation token 갱신 cron 필요 시 별도 task)"
    - "PR author = jeon-jonghyuk-taskctl-bot[bot] 강제"
    - "approver != PR author 강제 (시스템 승인자 사용)"
  merge_policy: "★ 본 task에서 만든 새 Guard 통과 시에만 머지 (drink your own champagne 두 번째)"
  ttl_hours: 12
```

## 8. 권장 진행 순서 (회장 명시)

1. 기존 lifecycle / gate / done 발행 경로 추적 (read-only)
2. **task-2467+3 실패 fixture를 먼저 테스트로 고정** (TDD 진입점)
3. fail marker / Gemini High / approver identity / merge SHA gate를 **공통 Guard로 구현** (`scripts/lifecycle_guards.py` 권장)
4. 기존 명령 경로에 Guard 연결 (P2)
5. 통합 테스트 실행 (P1 14건)
6. PR 생성 전 G3 verifier 재실행 (self-check)
7. evidence 포함 보고

## 9. goal_assertions (자동 검증)

- `python3 scripts/taskctl.py status task-2468` → state == DONE
- `gh pr view <task-2468 PR> --json author -q '.author.is_bot'` → true
- `gh pr view <task-2468 PR> --json mergedAt -q '.mergedAt'` → not null
- `git log origin/main --oneline | head -3` → task-2468 merge commit 존재
- `cat memory/orchestration-audit/admin-override.jsonl` → 본 task 항목 0건 (override 없음)
- `pytest tests/taskctl/test_lifecycle_guards.py -v` → 14 passed
- `pytest tests/taskctl/ tests/state_machine/ -v` → 전체 PASS
- `pyright scripts/taskctl.py scripts/lifecycle_guards.py` → 0 errors
- `ls memory/events/task-2468.done` → 존재 (MERGED 후)
- `ls memory/events/task-2468.done.escalated` → 부재 (합격 시)
- `ls memory/events/task-2468.g3-fail` → 부재 (합격 시)
- `python3 scripts/g3_independent_verifier.py --task-id task-2468` → PASS
- **task-2467+3 fixture 재현 + 차단 증명 로그**가 보고서에 포함됨

## 10. 시스템 청사진 연관

본 task = `system_bot_orchestration_blueprint_260506.md` 5층 자동화의 **L4 Audit + L3 Subagent 강화**:
- L4 evidence-based 승격 룰을 **코드로 강제**
- L3 Subagent (페룬)가 자기 자신의 거버넌스를 코드로 만들고 자기 자신을 검증
- track: `dev_workspace` (시스템 거버넌스)

## 11. 의존 task

- **선행** (이미 완료): task-2467+3 (PR #33 MERGED at `8d667080`)
- **후행**: 
  - task-2469 (Phase D — Penetration tests, composite-team)
  - task-2470 (Installation token 갱신 cron, dev6, optional)

## 12. 위임 완결성 4대 규칙

1. **수신 확인**: dispatch 출력 확인. 백업 cron 금지
2. **빌드+배포**: 본 task에서 만든 Guard로 자기 자신 머지 (drink your own champagne 2회차)
3. **실 E2E**: PR 생성 + bot author 검증 + Gemini gate (High 0건) + 시스템 승인자 approve + Guard 통과 + merge + main 반영
4. **구조 선행 파악**: 위임 전 `task-2467+3.md` 보고서 + `task-2467+3.g3-fail` + `task-2467+3.qc-result` 모두 read

## 13. 시스템 박제 메모

- 본 task의 목적 = **task-2467+3 silent corruption 패턴 재발 방지**
- 회장 명시: "문서만 수정한 PR은 완료로 인정하지 않음" → 코드 PR 필수
- 회장 인용: "이번 작업은 '문서화 task'가 아니다. 문서/보고서는 evidence이며, 실질 산출물은 코드 자동화와 테스트다."

## goal_assertions (auto-generated)
- `python3 scripts/taskctl.py status task-2468`
- `pytest tests/taskctl/test_lifecycle_guards.py -v`
- `cat memory/orchestration-audit/admin-override.jsonl`