# MERGED_CLOSE_BLOCKED_EXTERNAL 분류 룰 (영구 박제)

작성: 2026-05-07
근거: 회장 명시 (task-2483 사례 후 신설)

## 1. 문제 배경

- **task-2483** (BOT_GITHUB_TOKEN 갱신 사이클 복구)에서 PR #45가 정상 merge 완료(commit 37e26ed4)됐지만, post-merge `finish-task.sh` 단계에서 `git_evidence: NO_UNCOMMITTED` FAIL 발생
- 잔여물 정체: dev1 task-2479 영역 산출물 + systemd 운영 복사본 + 메인 workspace 시스템 활동 파일 (4 unstaged + 9 staged)
- → **본 task 본질 결함이 아니라 외부 workspace dirty가 close lifecycle을 차단**한 케이스
- retry 3회 초과로 봇이 `.escalate` 박제 + `task-timer.py end` 부수효과로 `.done`도 동시 발행 → 두 마커 모순 상태

## 2. 신규 분류

**MERGED_CLOSE_BLOCKED_EXTERNAL**

> 본질 작업 PASS + PR merge 정상 완료 + forbidden 위반 0 + admin override 0 + branch protection bypass 0이지만, post-merge close lifecycle(`finish-task.sh` / QC / `git_evidence`)이 본 task 외부의 workspace dirty 상태로 인해 실패한 상태.

## 3. 다른 분류와의 차이

| 분류 | merge 상태 | 차단 위치 | 차단 사유 | 본 task 책임 |
|---|---|---|---|---|
| `DONE` | MERGED | 없음 | 없음 | — |
| `ESCALATED` | OPEN/MERGED | 본질 단계 | 본질 결함, retry로 본질 재작업 필요 | 있음 |
| `DOGFOODING_PENDING` | MERGED 또는 머지 후 | dogfooding layer | 자기검증 외부 의존 (BOT 토큰, ruleset, approval) | 없음 |
| `MERGE_PENDING_DEPENDENCY` | **OPEN** | merge 자체 차단 | 후속 task 머지 의존 | 없음 |
| `MERGED_CLOSE_BLOCKED_EXTERNAL` | **MERGED** | post-merge close | 외부 workspace dirty | 없음 |
| `FAILED_PREEXISTING` | OPEN | 본질 진행 자체 | 기존 결함이 본 task 진행 차단 | 없음 |

핵심: MERGED_CLOSE_BLOCKED_EXTERNAL은 **이미 머지 됐다**는 점이 결정적. FAILED 계열로 분류하면 부정확.

## 4. 자동 감지 조건 (5항목)

다음 5가지 모두 만족 시 MERGED_CLOSE_BLOCKED_EXTERNAL 자동 분류:

1. ✅ PR MERGED (`gh pr view <#> --json mergedAt` not null)
2. ✅ admin override 0, ruleset bypass 0, forbidden 0 (보고서/감사 명시)
3. ✅ post-merge `finish-task.sh` / QC / `git_evidence` 단계 FAIL
4. ✅ 차단 사유가 본 task 외부 workspace 잔여물(타 task 영역 / 운영 복사본 / 시스템 활동 파일)
5. ✅ retry 3회 초과로 escalate 박제됨 (단 본질 재작업 무의미)

## 5. lifecycle 마커 보존 규칙

3개 마커 동시 보존:

- `.done`: 본질 작업 + merge 완료 evidence
- `.escalate`: post-merge close lifecycle 실패 evidence
- `.close-blocked-external`: 분류 evidence (JSON: classification, merge_status, close_blocker, lifecycle_state, rules, dependency)

⚠️ taskctl 최종 상태 = `MERGED_CLOSE_BLOCKED_EXTERNAL` (DONE 아님)

해소 시 `.close-blocked-external.resolved` 추가 + final_state_resolved=true 박제

## 6. 자동 조치 (5단계)

```
1. .close-blocked-external 박제 (JSON 페이로드)

2. .done과 .escalate 보존 (삭제 금지)

3. followup.txt 및 report에 MERGED_CLOSE_BLOCKED_EXTERNAL 판정 기록

4. 외부 잔여물 정리용 별도 task 발행
   - 작업 범위: 잔여물 식별 + 분류 + 정리/이동/unstage/ignore
   - 금지: 타 task 산출물 임의 삭제, 광역 파괴 명령 (git reset --hard 등)

5. 정리 task 완료 후 본 task finish-task.sh 재실행
   - 성공 시: .close-blocked-external 해제, MERGED_DONE 또는 DONE 정리, .escalate에 final_state_resolved=true 추가
   - 실패 시: 남은 blocker 보고, 자동 retry 금지
```

## 7. 금지 (회장 명시 3건)

- ❌ `.done`만 보고 최종 DONE 처리
- ❌ `.escalate` 삭제
- ❌ 실패 원인을 본 task 본질 실패로 오판

## 8. task-2483 사례 박제

- **PR**: #45 (merged at 2026-05-07T13:54:33Z, commit 37e26ed4)
- **본질**: refresh_bot_token.py 신설 + GitHub App credentials + JWT + installation token + audit jsonl + systemd unit 보강
- **forbidden 위반**: 0건 (보고서 + 마아트 독립 검증 PASS_WITH_NOTES)
- **차단**: `git_evidence: NO_UNCOMMITTED` (4 unstaged + 9 staged)
- **차단 owner**: dev1 task-2479 영역 / systemd 운영 복사본 / 메인 workspace 시스템 활동 파일
- **후속**: task-2484 main workspace hygiene cleanup → finish-task.sh 재실행

## 9. 시스템 결함 (Phase B 통합)

- `task-timer.py end`가 close 실패 케이스에도 `.done` 자동 생성 → 마커 모순
- `finish-task.sh`가 본 task 외부 영역 dirty까지 git_evidence 검사 → 분리 필요
- retry 룰이 외부 차단 사유 구분 없이 ESCALATED 분기 → 분류 자동화 필요
- 상세: `memory/orchestration/phase_b_integration_items_260507.md` (8종 분류 + dispatch.py 통합)
