# task-3012 — 머지·배포 통제 복구 (승인 게이트가 있는데 봇이 4회 머지했다)

**레벨**: Lv.2 (거버넌스) · **팀**: dev3-team (다그다) · **회장 승인 완료** (2026-08-25)

## 회장 지시
> **"나중에 머지/커밋/깃푸쉬/배포 관련해서 제대로 관리해야 함"**

## 배경 — 통제가 있는데 통하지 않았다

2026-08-25 하루에 **봇 자동 머지가 4회** 발생했다. 전부 태스크 명세에
*"PR 생성까지가 범위다. 머지는 ANU 가 한다. 절대 직접 머지하지 마라"* 를 명시했는데도다.

```
PR #251 task-3006   merged_by = jeon-jonghyuk-taskctl-bot[bot]
PR #252 task-3008   merged_by = jeon-jonghyuk-taskctl-bot[bot]
PR #253 task-3007   merged_by = jeon-jonghyuk-taskctl-bot[bot]
PR #7   task-3009   merged_by = jeon-jonghyuk-taskctl-bot[bot]   (InsuWiki)
```

### ★ ANU 실측 — 승인 게이트는 이미 존재한다
`scripts/taskctl.README.md` 의 **merge 단일 경로**:
```
1. state == HUMAN_APPROVED 검사 → FAIL 시 exit 1     ← 사람 승인 게이트
2. state ≠ CANCELLED 재검사
3. bash scripts/guard.sh pre-push <id>  → exit 0 강제
4. python3 scripts/qc_report_guard.py <id> → exit 0 강제
5. gh pr view <n> → mergeable=MERGEABLE + 8 required checks SUCCESS 강제
6. gh pr merge <n> --merge --delete-branch  (TASKCTL_INVOKED=1)
7. MERGED → DONE 전이
8. evidence.merge_timestamp 기록

★★★ BYPASS (회장 전용): TASKCTL_BYPASS=1 → 1~5단계 전부 skip
```

**즉 설계상으로는 사람 승인 없이 머지가 불가능하다. 그런데 4회 머지됐다.**

★ 2026-08-22 에 ANU 가 `prompts/DIRECT-WORKFLOW.md` 최상단 + 머지 실행 지점 3곳에
게이트 문구를 넣었으나(현재 4곳 존재), 그것은 **봇이 읽는 문서**다.
`taskctl` 은 **코드**라서 문서 게이트가 걸리지 않는다.

---

## ★ 이 태스크의 핵심 질문
**`HUMAN_APPROVED` 상태를 누가·언제·어떻게 세팅했는가?**

이것이 밝혀져야 통제를 복구할 수 있다. **추측하지 말고 기록으로 확정하라.**

## 할 일

### ① 4건의 머지 경로 추적 (조사 우선 — 고치기 전에)
각 PR 에 대해 다음을 **기록으로** 확정하라:
- `HUMAN_APPROVED` 로 전이된 시각과 **전이시킨 주체**
- `taskctl merge` 를 거쳤는가, 아니면 `gh api` 직접 호출인가
- `TASKCTL_BYPASS=1` 사용 흔적이 있는가
- `evidence.merge_timestamp` 등 감사 기록이 남아 있는가

★ 추적 실마리: `taskctl.py`(95KB) 의 상태 전이 로직 · `evidence` 저장 위치 ·
`scripts/lock_in_verify.py`(모든 `gh pr merge` 호출을 taskctl 경유로 강제하는 장치로 보인다) ·
`scripts/safe_cron_dispatch.py`(bot identity merge 탐지 로직 존재)

★ **CI 워처 경로**도 확인하라. `utils/pr_watcher_terminal_state_classifier.py` 가
`MERGE_READY` 를 산출한다. 그 판정이 곧바로 머지로 이어지는 배선이 있는지 확인하라.
있다면 **그것이 승인 게이트를 우회하는 경로**다.

### ② 원인에 맞는 통제 복구
조사 결과에 따라 다르므로 **①을 마친 뒤 ANU 에 안을 제출하고 승인받아라.**
예상 방향(확정 아님):
- `MERGE_READY` **판정**과 **실제 merge 실행**을 분리 — 판정은 자동, 실행은 사람 승인 후
- `HUMAN_APPROVED` 전이를 **사람만** 할 수 있게(봇 자동 전이 차단)
- 머지 수행 주체·이벤트 자체에 거는 **통합 게이트**(세션 단위가 아니라)

★ **`TASKCTL_BYPASS` 를 없애지 마라.** 회장 전용 비상구다. 대신 **사용 시 감사 기록**이 남게 하라.

### ③ 커밋·푸시·배포까지 함께 본다 (회장 지시)
머지만이 아니라 파이프라인 전체가 대상이다.
- **커밋/푸시**: 봇이 `main`/`master` 에 직접 푸시할 수 있는가? Ruleset 이 막고 있는가?
  (ANU 실측: InsuRo 는 Ruleset ON — 직접 커밋 시 *"Changes must be made through a pull request"* 로 거부됨.
   **InsuWiki 도 같은지 확인**하라)
- **배포**: 백엔드 배포는 `scripts/deploy/insuro-deploy.sh <sha>` 단일 경로다(task-2988).
  봇이 이걸 임의 실행할 수 있는지, 실행 기록이 남는지 확인하라
- 각 단계에서 **누가 무엇을 했는지 사후에 추적 가능한지** 점검하고, 공백이 있으면 보고하라

---

## ★ 금지 · 주의
- **통제를 느슨하게 만드는 방향 금지.** 이 태스크는 조이는 것이다
- **`TASKCTL_BYPASS` 제거 금지** (회장 비상구)
- **진행 중 태스크 방해 금지** — 지금 dev5(task-3010) · dev2(task-3011) 이 돌고 있다.
  그들의 PR 생성·정상 워크플로를 막지 마라
- `server/**` · `src/**` · `extension/**` 등 **제품 코드 수정 금지**. 이 태스크는 운영 도구 영역이다
- ① 조사 없이 ②를 먼저 하지 마라. **원인 모르고 고치면 우회로만 옮겨간다**

## allowed_resources

```yaml
allowed_resources:
  paths:
    - "scripts/taskctl.py"
    - "scripts/taskctl.README.md"
    - "scripts/lock_in_verify.py"
    - "scripts/safe_cron_dispatch.py"
    - "utils/pr_watcher_terminal_state_classifier.py"
    - "utils/ci_watch_handoff_runner.py"
    - "prompts/DIRECT-WORKFLOW.md"
    - "scripts/__tests__/**"
    - "memory/reports/task-3012.md"
  forbidden_paths:
    - "projects/**"
    - "memory/plans/tasks/**"
    - "memory/events/**"
  commands:
    - "python3"
    - "bash"
    - "gh"
    - "pytest"
  merge_policy: "analysis_first"
  ttl_hours: 72
```

## 검증
1. **4건 경로 추적표** — PR별로 `HUMAN_APPROVED` 전이 주체·시각·경로를 표로 제시
2. **재현** — 승인 없이 머지가 되는 경로를 **실제로 재현**하라(dry-run 또는 테스트 PR).
   재현 못 하면 "재현 실패"라고 정직히 적어라. **추정으로 원인을 단정하지 마라**
3. **수정 후 차단 실증** — 같은 경로가 막히는지 확인
4. **정상 경로 무손상** — ANU 가 승인한 머지는 여전히 되는지 확인
5. **봉인** — 통제가 다시 느슨해지면 FAIL 하는 테스트. **변이로 실증**하라
6. 기존 테스트 회귀 유지

## 운영 계약
- 대상 저장소: `/home/jay/workspace` (운영 도구 저장소)
- ★ `gh` 호출 시 `GH_TOKEN="$BOT_GITHUB_TOKEN"` 주입 필수 (회장 개인 PAT 금지 — 감사기록 오염)
- 워크플로우 `/home/jay/workspace/prompts/DIRECT-WORKFLOW.md` · QC `/home/jay/workspace/teams/shared/QC-RULES.md`
- `WORKSPACE_ROOT=/home/jay/workspace` · `CHAT_ID=6937032012` · 수집자 key `ANU_KEY=c119085addb0f8b7`
- 완료 경로는 `finish-task.sh` 실행이 유일하다. 수동 `.done` 금지.
- **명세와 실측이 다르면 임의 판단하지 말고 ANU 에 보고하라.**

## 완료 조건
4건 경로 추적표(기록 기반) · 우회 경로 재현 또는 재현실패 명시 · 통제 복구안 ANU 승인 후 적용 ·
차단 실증 · 정상 경로 무손상 · 커밋/푸시/배포 추적 공백 점검 결과 · 변이로 봉인 실증

## 보고
**★★★ 이 태스크는 특히 스스로 머지하지 마라.** 머지 통제를 고치는 태스크가 통제를 어기면 자기모순이다.
`memory/reports/task-3012.md` 작성 후 표준 완료 콜백 등록. 콜백 프롬프트 **UTF-8 3900 bytes 이하**.
★ 봉투 첫 줄에 **"HUMAN_APPROVED 전이 주체 규명 여부"** 를 담아라. 이것이 이 태스크의 결론이다.