# task-3016 — 머지·배포 통제 복구 (t3012 이어받기 · 실측 갱신본)

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

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

## ★ 이것은 t3012 이어받기다
t3012 가 23분 조사 후 세션이 끊겼다(worktree 미생성·보고서 0).
마지막 응답에서 다음을 조사 중이었다:
- `lock_in_verify.py` 가 죽은 장치인지
- CI 워처 `MERGE_READY` 판정 → 머지 실행 배선 존재 여부
- InsuWiki Ruleset 유무, `bypass_actors` 에 봇이 있는지
- 배포 스크립트 실행 주체 추적 가능성

**백지에서 다시 하지 마라. 위 지점부터 이어가라.** (Codex 판단: 백지 재조사는 오늘 반복된
ANU 오진을 재생산할 위험이 크다)

---

## ★ ANU 실측 갱신 (2026-08-25 20:00, 이전 명세의 수치를 정정한다)

오늘 머지된 8건의 **실제 머지 주체**를 `merged_by` 로 확정했다:

```
taskctl-bot[bot] 머지 = 6건
  InsuRo  #249 t3004(04:41) · #252 t3008(04:14) · #253 t3007(04:54) · #255 t3014(08:36)
  InsuWiki #6 t3001(03:27) · #7 t3009(05:16)

JonghyukJeon(회장 계정) 머지 = 2건
  InsuRo #251 t3006(01:59) · InsuWiki #8 t3011(07:21)
  ★ 이 2건은 ANU 가 머지한 것이다. GH_TOKEN="$BOT_GITHUB_TOKEN" 을 빠뜨려
    회장 개인 PAT 로 인증돼 감사기록이 오염됐다. **ANU 자신의 규칙 위반이다.**
```

### 즉 문제가 두 종류다 — 섞지 마라
- **문제 A**: 봇이 ANU 승인 없이 머지 (6건). `taskctl merge` 1단계에
  `state == HUMAN_APPROVED` 검사가 **이미 있는데도** 발생했다
- **문제 B**: 사람(ANU)이 **잘못된 자격증명**으로 머지 (2건). 누가 했는지 기록이 왜곡된다

## ★ 핵심 질문
**A: `HUMAN_APPROVED` 를 누가·언제·어떻게 세팅했는가?**
**B: 봇 토큰 미주입을 어떻게 구조적으로 막을 것인가?**

---

## 할 일

### ① 문제 A 경로 추적 (조사 우선 — 고치기 전에)
6건 각각에 대해 **기록으로** 확정하라:
- `HUMAN_APPROVED` 전이 시각과 **전이 주체**
- `taskctl merge` 경유인가, `gh api` 직접 호출인가
- `TASKCTL_BYPASS=1` 흔적
- `evidence.merge_timestamp` 등 감사 기록 잔존 여부

★ 실마리: `scripts/taskctl.py`(95KB) 상태 전이 · `scripts/lock_in_verify.py`(모든 `gh pr merge`
를 taskctl 경유로 강제하는 장치로 보임) · `scripts/safe_cron_dispatch.py`(bot identity merge 탐지) ·
`utils/pr_watcher_terminal_state_classifier.py`(MERGE_READY 산출)

★ **CI 워처 경로**를 특히 보라. `MERGE_READY` 판정이 곧바로 머지로 이어지는 배선이 있다면
그것이 승인 게이트 우회로다.

### ② 문제 B — 토큰 미주입 방지
`gh` 호출에 `GH_TOKEN="$BOT_GITHUB_TOKEN"` 이 빠지면 **회장 PAT 로 폴백**된다.
- 이를 **구조적으로** 막을 방법을 제안하라(래퍼 · 환경 강제 · 사전 검사 등)
- ★ **회장 PAT 자체를 못 쓰게 만들지는 마라.** 회장 본인이 쓸 수 있어야 한다.
  막을 대상은 "의도치 않은 폴백"이다
- `safe_cron_dispatch.py` 에 이미 `owner_pat fallback` 탐지 로직이 있다. 재사용 가능한지 보라

### ③ 커밋·푸시·배포 추적 (회장 지시 범위)
- **푸시**: InsuRo 는 Ruleset ON 실측 확인(직접 커밋 시 *"Changes must be made through a pull request"*).
  **InsuWiki 도 같은지 확인**하라
- **배포**: `scripts/deploy/insuro-deploy.sh <sha>` 단일 경로. 봇이 임의 실행 가능한지, 기록이 남는지
- ★ **오늘 실제 사고**: InsuRo·InsuWiki 양쪽에서 "머지했는데 로컬/서빙이 뒤처져 반영 안 됨"이
  각 1회 발생해 ANU 가 `git pull` 로 수습했다. **머지와 배포의 괴리를 탐지할 수단**이 있는지 점검하라
  (InsuRo 는 `insuro-drift-monitor` 가 있다. InsuWiki 는?)

### ④ 복구안은 ANU 승인 후 적용
①②③ 조사를 마치면 **안을 제출하고 ANU 승인을 받아라.** 조사 없이 고치지 마라.
예상 방향(확정 아님): `MERGE_READY` 판정과 merge 실행 분리 · `HUMAN_APPROVED` 전이를 사람만 가능하게 ·
머지 수행 주체/이벤트에 거는 통합 게이트

★ **`TASKCTL_BYPASS` 를 없애지 마라** (회장 전용 비상구). 대신 **사용 시 감사 기록**을 남겨라.

---

## 금지
- **통제를 느슨하게 만드는 방향** — 이 태스크는 조이는 것이다
- **진행 중 작업 방해** — 현재 PR #256(t3010) 이 CI 대기 중이다. 정상 워크플로를 막지 마라
- `projects/**` 제품 코드 수정 — 이 태스크는 운영 도구 영역이다
- ① 조사 없이 ④를 먼저 하기

## 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-3016.md"
  forbidden_paths:
    - "projects/**"
    - "memory/plans/tasks/**"
    - "memory/events/**"
  commands:
    - "python3"
    - "bash"
    - "gh"
    - "pytest"
  merge_policy: "analysis_first"
  ttl_hours: 72
```

## 검증
1. **6건 경로 추적표** — PR별 `HUMAN_APPROVED` 전이 주체·시각·경로
2. **재현** — 승인 없이 머지되는 경로를 실제로 재현(dry-run/테스트 PR).
   못 하면 **"재현 실패"라고 정직히** 적어라. 추정으로 단정하지 마라
3. **토큰 폴백 재현** — `GH_TOKEN` 없이 `gh api` 호출 시 어떤 계정으로 인증되는지 실측
4. **수정 후 차단 실증** · **정상 경로 무손상**(ANU 승인 머지는 여전히 가능)
5. **봉인** — 통제가 다시 느슨해지면 FAIL 하는 테스트. **변이로 실증**

## 운영 계약
- 대상 저장소: `/home/jay/workspace`
- ★ `gh` 호출 시 `GH_TOKEN="$BOT_GITHUB_TOKEN"` 주입 필수. **이 태스크가 그 규칙을 다루면서
  스스로 어기면 자기모순이다.**
- 워크플로우 `/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개 세션이 `status=ok` 로 끝나면서
보고서·PR 을 남기지 못했다(t3012 포함). **조사 결과를 보고서에 수시로 적어라.**

## 완료 조건
6건 경로 추적표 · 토큰 폴백 실측 · 우회 재현 또는 재현실패 명시 · 복구안 ANU 승인 후 적용 ·
차단 실증 · 정상 경로 무손상 · 머지↔배포 괴리 탐지 수단 점검 · 변이로 봉인 실증

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