# task-2494 Phase 0 — Stuck/Zombie Detection Hardening Spec

작성: 2026-05-08  
작성자: 스바로그 (개발6팀 백엔드 담당)  
위임자: 페룬 (팀장)  
단계: Phase 0 — 문서화/스펙 보강 (코드/테스트/PR/branch 변경 일체 금지)  
근거 incident: task-2487 (오딘, dev2-team)

> 회장 명시 (2026-05-08T02:55): stuck/zombie detection은 계속 Phase 0 문서화/감사 범위로 유지. 즉시 production 통합 X

---

## §1 Incident Summary

**목적**: task-2487 사건의 전체 시간선과 정량 지표를 박제하여 이후 detection spec의 근거 자료로 삼는다.

### 1.1 시간선

| 시점 | 이벤트 |
|---|---|
| PR #49/#50/#51 발행 | 오딘이 Group A/B/C 3건 PR 발행. CI 모두 SUCCESS. |
| PR 발행 후 ~1시간 | lifecycle marker 0건 발생. 봇 idle 상태 지속. |
| ~02:50 | 회장 강제 stop. 오딘 세션 종료. |
| stop 직후 | 아누(개발실장)가 '정상 머지 대기'로 최초 오진단 → 회장 stop 후 오판 인정 → stuck으로 재분류 |
| 2026-05-08T02:55 | 회장이 task-2494 candidate spec 발행. STUCK_AFTER_PR_OPEN 분류 명시. |
| 2026-05-08T04:10 | 회장이 두 incident type(STUCK_AFTER_PR_OPEN / ESCALATED_VERIFIER_LIMITATION) 명시적 구분 발령. |

### 1.2 PR별 정량 지표

| PR | 대상 | CI 상태 | mergeStateStatus | unresolved threads | 주요 회귀 지적 |
|---|---|---|---|---|---|
| PR #49 | Group A dispatch | SUCCESS | BLOCKED | 4건 | legacy task-N.M dot-phase 호환 깨짐 |
| PR #50 | Group B scripts | SUCCESS | BLOCKED | 6건 | notify-completion.py sys.path 누락 |
| PR #51 | Group C dashboard/report | SUCCESS | BLOCKED | 7건 | V2 regex DRY 위반 |
| **합계** | — | — | **전건 BLOCKED** | **17건** | — |

### 1.3 차단 원인

- branch protection ruleset_id **15896715** `main-protection`이 `required_review_thread_resolution=true`로 설정.
- Gemini reviewer가 남긴 review thread는 단순 코멘트가 아닌 **실제 회귀** 지적 (legacy 호환 파괴, sys.path 누락, DRY 위반 등).
- auto-merge.yml 파일이 main 브랜치에 **부재** (workflow registry 등록은 있으나 main에 파일 없음). PR #17 / task-2444 이후 trigger 0회.
- PR 발행 후 1시간 동안 다음 lifecycle marker **0건**: PR merged / .done / .followup / .escalate / BLOCKED 사유 보고 / timer 종료.

### 1.4 아누 진단 오류

- 최초 진단: "정상 머지 대기" — CI green을 보고 단순 approval 대기로 오분류.
- 오류 근거: unresolved review thread 17건 및 mergeStateStatus BLOCKED 미확인.
- 회장 stop 후 오판 인정 → STUCK_AFTER_PR_OPEN + REVIEW_OR_APPROVAL_PENDING_WITH_REGRESSION 재분류.
- 이 진단 오류가 본 spec의 1차 동기: **시스템 차원 자동 분류 부재가 인간 오판을 보정하지 못함**.

---

## §2 Problem Definition

**목적**: 본 spec이 다루는 문제 범위를 STUCK_AFTER_PR_OPEN으로 명확히 한정하고, 혼동 가능한 인접 incident type과 분리한다.

### 2.1 본 spec의 scope

**본 spec이 다루는 incident type: STUCK_AFTER_PR_OPEN 단독.**

ESCALATED_VERIFIER_LIMITATION은 별도 분류 문서에서 처리한다.

> 회장 명시 (2026-05-08T04:10): task-2494 본 task가 다루는 것은 STUCK_AFTER_PR_OPEN만. ESCALATED_VERIFIER_LIMITATION은 별도 분류(`memory/feedback/feedback_escalated_verifier_limitation_classification_260508.md`)에서 처리.

### 2.2 두 incident type 구분표

| 항목 | STUCK_AFTER_PR_OPEN | ESCALATED_VERIFIER_LIMITATION |
|---|---|---|
| 트리거 사례 | task-2487 (오딘) | task-2485+1 (헤르메스) |
| 본질 분류 | REVIEW_OR_APPROVAL_PENDING_WITH_REGRESSION | ESSENCE_PASS / ESCALATED_VERIFIER_LIMITATION |
| PR 상태 | OPEN + CI 완료 + BLOCKED | 머지 완료 |
| 본질 합격 여부 | 미확인 / 회귀 존재 | 100% PASS |
| 봇 idle | 1시간 이상 | 해당 없음 |
| lifecycle marker | 부재 | .escalate 마커 존재 |
| detection signal | 봇 idle + lifecycle marker 부재 + PR open + CI 완료 | PR merged + 본질 100% PASS + verifier .escalate 마커 |
| 별도 spec 경로 | 본 문서 | `memory/feedback/feedback_escalated_verifier_limitation_classification_260508.md` |

### 2.3 문제 진술

> "PR open 이후 일정 시간 내 lifecycle 종료 신호 부재 → 시스템 차원에서 stuck/zombie 분류 부재 → 아누 진단 오판/회장 수동 stop 의존"

구체적으로:

1. 봇이 PR을 발행한 후 idle 상태로 전환되어도 시스템이 이를 감지하지 못한다.
2. CI SUCCESS + mergeStateStatus BLOCKED 조합이 "정상 진행 중"처럼 보여 오판을 유발한다.
3. unresolved review thread 수를 자동으로 집계·보고하는 경로가 없다.
4. 1시간 무반응에도 alert/escalate가 발생하지 않아 회장 수동 개입에 의존한다.
5. 아누의 수동 진단 오류를 보정할 자동 분류 레이어가 없다.

---

## §3 Absent Signals

**목적**: task-2487 incident에서 관찰 기간(1시간) 동안 하나도 발생하지 않은 lifecycle marker 6종을 정의한다.

### 3.1 Absent Lifecycle Signal 목록

| # | signal | 정의 | 정상 발생 시점 | 관찰 채널 |
|---|---|---|---|---|
| 1 | PR merged | PR이 base 브랜치에 머지 완료된 상태 | CI PASS + review 완료 + protection rule 충족 후 | gh api graphql mergeStateStatus = MERGED |
| 2 | .done 발행 | `memory/events/{task_id}.done` 파일 생성 | PR merged + close lifecycle 완료 후 | filesystem glob |
| 3 | .followup 보고 | `memory/events/{task_id}.followup.txt` 파일 생성 | 후속 작업 필요 사항 발견 시, 또는 blocked 상태 보고 시 | filesystem glob |
| 4 | .escalate 발행 | `memory/events/{task_id}.escalate` 파일 생성 | 본질 결함 또는 처리 불가 상황 발생 시 | filesystem glob |
| 5 | BLOCKED 사유 보고 | mergeStateStatus BLOCKED 사유를 팀 채널 또는 .followup으로 명시 보고 | PR 발행 후 첫 상태 확인 시점 | .followup.txt 또는 groupchat log |
| 6 | timer 종료 | `task-timer.py end <task_id>` 실행 완료 | task 완료/중단 시 | task-timers.json |

### 3.2 관찰 가능 여부

모든 6종 signal은 filesystem 또는 gh api를 통해 자동 폴링 가능하다. 부재 판정 기준: threshold 시간 경과 후 6종 중 하나도 존재하지 않는 경우 (threshold 후보값은 §4.3 참조).

---

## §4 Detection Conditions

**목적**: STUCK_AFTER_PR_OPEN 자동 분류를 위한 전체 detection condition을 정의한다. 후보 spec 5개 state를 기반으로, task-2487 evidence에서 도출한 추가 condition을 신규 추가한다.

### 4.1 기존 5개 Detection State (후보 spec 기반)

| state 키 | 조건 | task-2487 관측값 |
|---|---|---|
| `pr_state` | PR open + CI 완료 + mergeStateStatus BLOCKED | PR #49/#50/#51 모두 해당 |
| `review_state` | unresolved review thread 존재 | 총 17건 (PR #49: 4, PR #50: 6, PR #51: 7) |
| `bot_state` | 봇 세션 idle 지속 | 1시간 동안 idle |
| `timer_state` | task timer active 또는 lifecycle marker 미종료 | task timer 유지 중, lifecycle 미종료 |
| `report_state` | 보고서 미발행 | .followup / BLOCKED 사유 보고 0건 |

### 4.2 추가 Detection Conditions (task-2487 evidence 기반, 신규 7건)

| # | condition 키 | 조건 | 도출 근거 (task-2487 evidence) |
|---|---|---|---|
| 6 | `auto_merge_workflow_absent` | `.github/workflows/auto-merge.yml`이 main 브랜치에 부재 | auto-merge.yml main 브랜치 없음 확인. PR #17/task-2444 이후 trigger 0회. green path auto-approve 경로 단절. |
| 7 | `gemini_review_actor_unresolved` | Gemini reviewer가 남긴 review thread가 unresolved 상태로 존재 | PR #49/#50/#51의 17건 thread 전부 Gemini actor. Gemini thread는 단순 코멘트가 아닌 실제 회귀 지적. |
| 8 | `merge_queue_not_used` | PR이 merge queue를 사용하지 않고 일반 OPEN 상태 유지 | PR #49/#50/#51 merge queue 미진입. branch protection 규칙과 연동 없음. |
| 9 | `branch_protection_thread_resolution_active` | branch protection ruleset에 `required_review_thread_resolution=true` 활성화 | ruleset_id 15896715 main-protection에서 해당 설정 확인. CI SUCCESS임에도 BLOCKED 사유. |
| 10 | `bot_last_activity_stale` | 봇 세션의 마지막 활동 timestamp가 threshold 이상 경과 | 오딘 세션이 PR 발행 후 추가 commit/comment/marker 0건으로 활동 부재 |
| 11 | `dispatch_lock_not_released` | 해당 task의 dispatch lock이 해제되지 않은 채 봇 idle | stuck 상태에서 dispatch lock 미해제 → 동일 task 재위임 불가 상태 유지 |
| 12 | `regression_in_review_thread` | unresolved review thread의 내용이 본질 합격 조건과 충돌하는 회귀 지적 포함 | Gemini thread: legacy task-N.M dot-phase 호환 깨짐 / sys.path 누락 / V2 regex DRY 위반 — 모두 task-2487 본질 요건과 직접 충돌 |

### 4.3 threshold 후보값 (회장 결정 사항)

> 회장 결정 사항: 아래 후보값은 spec 시점 제안이며, 실제 threshold는 회장이 별도 결정한다.

| threshold | 의미 | 권장 상황 |
|---|---|---|
| 30분 | 단기 조기 경고 | critical chain task 또는 고우선순위 task |
| 60분 | 표준 stuck 감지 | 일반 task (task-2487 실제 경과 시간 기준) |
| 120분 | 장기 zombie 감지 | MERGE_PENDING_DEPENDENCY 등 조건부 대기 정상 케이스 제외 후 |

### 4.4 False Positive Guard (4건 이상)

| # | 정상 케이스 | 제외 조건 | 근거 |
|---|---|---|---|
| 1 | 정상 머지 대기 | CI green + unresolved threads 0건 + auto-merge workflow 정상 동작 중 | 모든 review thread resolved + CI PASS = 실제 stuck 아님 |
| 2 | 인간 개입 진행 중 | WAITING_FOR_CHAIR_DECISION 마커 존재 또는 회장 결정 대기 명시 | 회장 결정 대기 상태는 봇 idle이 정상 |
| 3 | 의존 task 머지 대기 | MERGE_PENDING_DEPENDENCY 분류 마커 존재 + 의존 task_id 명시 | 의존 task 미완료로 인한 PR OPEN 유지는 stuck이 아닌 정상 대기 |
| 4 | dogfooding pending | DOGFOODING_PENDING 분류 마커 존재 + 외부 의존 명시 | 외부 인프라 의존으로 인한 대기는 별도 분류 적용 |
| 5 | 회귀 픽스 진행 중 | 후속 +1 task가 active 상태이고 원 PR이 의도적으로 OPEN 유지 | task-2487+1처럼 회귀 픽스 중인 경우 원 PR OPEN 유지는 정상 |

---

## §5 Auto Handling Policy

**목적**: STUCK_AFTER_PR_OPEN 감지 후 detector가 자동으로 수행하는 처리 절차를 정의한다. 실제 구현 전 dry-run 우선 원칙(★ 데몬 안전 원칙)을 명시하고, sense/think/act 3분리 책임을 확립한다.

### 5.1 데몬 안전 원칙 (최우선)

> ★ 데몬 안전 원칙: 모든 detector 구현은 dry-run-first로 설계한다. 실제 파일 생성/수정 전 반드시 dry-run 모드에서 검증 완료 후 운영 모드 전환.

```
# 의사코드 (실행 불가 예시)
detector.run(mode="dry-run")   # 먼저 검증
# 결과 확인 후
detector.run(mode="live")      # 운영 전환
```

### 5.2 Sense → Think → Act 3분리 책임

| 단계 | 역할 | 담당 모듈 후보 | 허용 동작 | 금지 동작 |
|---|---|---|---|---|
| **Sense** | 상태 데이터 수집만 | `stuck_detector.sense()` | PR state 조회, review thread count 조회, timer status 조회, last activity 조회 | 어떤 marker도 생성/수정 금지 |
| **Think** | 수집 데이터 기반 판정만 | `stuck_detector.think()` | threshold 비교, false positive guard 적용, 분류 결정 | 외부 API write 호출 금지 |
| **Act** | 판정 결과 기반 처리만 | `stuck_detector.act()` | .followup 생성, 회장 알림, 분류 기록 | §6 Forbidden Actions에 해당하는 일체 동작 금지 |

### 5.3 Auto Handling 5단계 시퀀스

```
[SENSE] PR state poll + review thread count + timer status + bot last activity
    |
    v
[THINK] threshold 초과 여부 판정
    |
    +-- false_positive_guard PASS? --> 제외 (정상 케이스 기록)
    |
    v
[THINK] STUCK_AFTER_PR_OPEN 분류 결정
    |
    v
[ACT STEP 1] STUCK_AFTER_PR_OPEN 분류 기록
    memory/events/{task_id}.stuck-{timestamp} 생성

    |
    v
[ACT STEP 2] 봇 세션 종료 또는 재시작 후보 등록
    (실제 세션 종료는 회장/팀장 승인 후 실행)
    dry-run 출력: "session {bot_id} → idle pool 복귀 후보"

    |
    v
[ACT STEP 3] .followup 자동 생성
    memory/events/{task_id}.followup.txt 생성
    내용: stuck 분류 근거 + evidence snapshot 경로 + 후속 조건

    |
    v
[ACT STEP 4] 회장 통합 요약 보고
    단일 요약 메시지: task_id / 경과 시간 / PR state / unresolved threads / 분류

    |
    v
[ACT STEP 5] 재위임 정책 적용 (§8 기준)
    동일 task 재위임 시 새 세션 사용 → 기존 stuck 봇 세션 재사용 금지
```

### 5.4 Detector가 만질 수 있는 marker / 만지면 안 되는 marker

| marker | detector 접근 가능 여부 | 이유 |
|---|---|---|
| `{task_id}.stuck-{timestamp}` | **생성 가능** (Act Step 1) | 신규 stuck 분류 기록용 |
| `{task_id}.followup.txt` | **생성 가능** (Act Step 3) | stuck 보고용. 기존 파일 덮어쓰기 금지, append-only |
| `{task_id}.done` | **접근 금지** | stuck 상태에서 .done 생성은 §6 Forbidden Action #1 |
| `{task_id}.escalate` | **접근 금지** | .escalate 없이 .followup만 생성도 금지 (§6 #8). .escalate 단독 판단 금지 |
| `{task_id}.merge-pending` | **읽기만 가능** | false_positive_guard 판정에 사용. 수정 금지 |
| `{task_id}.waiting-chair` | **읽기만 가능** | false_positive_guard 판정에 사용. 수정 금지 |
| 다른 task의 모든 marker | **접근 금지** | cross-task marker 수정 금지 (§6 #10) |

---

## §6 Forbidden Actions

**목적**: STUCK_AFTER_PR_OPEN 분류 및 처리 과정에서 detector/봇/팀원이 절대로 취해서는 안 되는 행동을 나열한다. 각 금지 항목에는 사유를 명시한다.

### 6.1 기존 4건 (회장 명시, 후보 spec 기반)

| # | 금지 행동 | 사유 |
|---|---|---|
| 1 | stuck 상태에서 `.done` 생성 | task가 완료되지 않은 상태에서 완료 마커 발행 → 후속 lifecycle 오염. task-timer.py end --reason done 사용 금지. 적절한 STUCK 분류 명시 필수. |
| 2 | unresolved review thread 단순 resolve | Gemini thread는 실제 회귀 지적. 내용 검토 없이 resolve하면 회귀 숨김. |
| 3 | admin override | branch protection rule 우회. 정책 위반이자 회귀 은폐. |
| 4 | 기존 stuck 봇에 추가 작업 계속 투입 | idle/stuck 세션에 추가 명령 주입은 예측 불가 동작 유발. |

### 6.2 추가 8건 (신규, task-2487 evidence 기반)

| # | 금지 행동 | 사유 |
|---|---|---|
| 5 | PR force merge / 강제 머지 | branch protection 규칙이 unresolved thread 차단. 강제 머지는 17건 회귀 지적 무시 + 정책 위반. |
| 6 | branch protection ruleset 우회 | ruleset_id 15896715 main-protection은 회귀 방지 목적. 우회 시 회귀 main 진입. |
| 7 | 봇이 unresolved review thread를 임의 resolve | Gemini reviewer가 지적한 실제 회귀를 봇이 내용 확인 없이 resolve하면 회귀 은폐 + Gemini 리뷰 무력화. |
| 8 | `.escalate` 없이 `.followup`만 생성 | .followup 단독 생성은 분류 정보 누락. stuck 상태에서 .escalate도 판단 불가 시 STUCK 분류 마커로 대체. |
| 9 | stuck 분류 시 `task-timer end --reason done` 실행 | stuck 상태는 done이 아님. 적절한 stuck 분류 reason 명시 필수. (현재 --reason stuck 옵션 미존재 → §10 implementation candidate) |
| 10 | detector가 다른 task의 marker 파일 수정 | cross-task marker 수정은 다른 task lifecycle 오염. detector 스코프는 감지 대상 task 단독. |
| 11 | cross-team session 하이재킹 | 타 팀(예: dev2-team 오딘 세션)에 직접 명령 주입. 팀 격리 원칙 위반. |
| 12 | critical chain task 자동 stop | critical chain 위 task의 자동 stop은 chain 전체에 cascading 영향. 회장 명시 결정만 허용. |

---

## §7 Evidence Preservation Policy

**목적**: STUCK_AFTER_PR_OPEN 분류 시점에 캡처해야 하는 evidence의 종류, 경로, 보존 원칙을 정의한다.

### 7.1 Stuck 분류 시점 evidence 캡처 항목

| # | 항목 | 수집 방법 | 포함 내용 |
|---|---|---|---|
| 1 | PR state JSON | `gh api repos/.../pulls/{pr}` | PR number, title, state, mergeStateStatus, base/head ref, created_at |
| 2 | Review threads | `gh api graphql` (reviewThreads) | thread id, resolved 여부, body 발췌, actor, createdAt |
| 3 | Bot session log | member-status.json 또는 세션 로그 | 마지막 활동 timestamp, idle 시작 시점 |
| 4 | Timer status | `task-timer.py status <task_id>` | 시작 시간, 경과 시간, 상태 |
| 5 | Lifecycle marker 검색 결과 | filesystem glob | .done / .followup / .escalate / .stuck 파일 존재 여부 + 경로 |
| 6 | auto-merge workflow 상태 | `gh api repos/.../contents/.github/workflows/auto-merge.yml` | 파일 존재 여부, 마지막 수정 commit |
| 7 | branch protection ruleset | `gh api repos/.../rulesets/{ruleset_id}` | required_review_thread_resolution 값 |

### 7.2 보존 경로

```
memory/events/{task_id}.stuck-evidence-{timestamp}.json
```

예시:
```
memory/events/task-2487.stuck-evidence-20260508T025000.json
```

timestamp 형식: `YYYYMMDDTHHMMSS` (UTC 또는 +09:00 명시)

### 7.3 보존 원칙

- **append-only**: evidence 파일 내용 수정 금지. 추가 정보는 별도 파일로 생성.
- **보존 기간**: 최소 30일. critical chain 관련 task는 chain 완료 후 추가 30일.
- **원본 보존**: task-2485+1 사례의 `.done` / `.escalate` / `.done.escalated` 모두 보존 원칙 차용. stuck evidence도 재분류 후에도 원본 삭제 금지.
- **접근 권한**: evidence 파일 read-only 처리. detector가 기존 evidence 파일 수정 금지.
- **evidence 불완전 시 처리**: 일부 항목 수집 실패 시 수집 실패 사유를 evidence JSON에 포함하고 나머지 항목으로 stuck 판정 진행.

### 7.4 evidence JSON 스키마 (후보)

```json
{
  "task_id": "task-2487",
  "classification": "STUCK_AFTER_PR_OPEN",
  "detected_at": "2026-05-08T02:50:00+09:00",
  "threshold_exceeded_minutes": 60,
  "pr_states": [
    {
      "pr_number": 49,
      "state": "OPEN",
      "mergeStateStatus": "BLOCKED",
      "ci_status": "SUCCESS",
      "unresolved_threads": 4
    }
  ],
  "absent_lifecycle_signals": ["PR merged", ".done", ".followup", ".escalate", "BLOCKED 사유 보고", "timer 종료"],
  "auto_merge_workflow_present": false,
  "bot_last_activity_at": "<timestamp>",
  "collection_failures": []
}
```

---

## §8 Redelegation Policy

**목적**: STUCK_AFTER_PR_OPEN으로 분류된 task를 재위임할 때 적용하는 절차와 원칙을 정의한다.

### 8.1 핵심 원칙

> 동일 task 재위임 시 반드시 새 세션 사용. 기존 stuck 봇 세션 재사용 금지.

근거: task-2487+1에서 오딘 기존 세션 재사용이 금지로 박제됨. stuck 세션의 상태가 예측 불가하며 추가 오동작 위험.

### 8.2 Bot Session 회수 절차

| 단계 | 행동 | 담당 |
|---|---|---|
| 1 | stuck 세션 idle 확인 | detector (Sense 단계) |
| 2 | 세션을 idle pool 복귀 후보로 등록 | detector (Act Step 2, dry-run 출력) |
| 3 | 회장/팀장 승인 후 실제 세션 종료 | 팀장 또는 회장 |
| 4 | idle pool 복귀 또는 강제 종료 처리 | 운영 담당 |
| 5 | dispatch_lock 해제 | dispatch 시스템 |

세션 강제 종료 전: evidence 캡처 완료 여부 확인. 미완료 시 evidence 우선 수집.

### 8.3 새 세션 Dispatch 조건

새 세션으로 동일 task를 재위임하기 위해서는 다음 조건을 모두 충족해야 한다:

| # | 조건 | task-2487 기준 사례 |
|---|---|---|
| 1 | 선행 의존 task 머지 완료 | task-2485+1 (PR #47) 머지 완료 |
| 2 | 회귀 픽스 완료 | task-2487+1 회귀 픽스 완료 (17건 unresolved thread 사유 해소) |
| 3 | critical chain 안정화 | PR #49/#50/#51 순차 머지 완료 |
| 4 | 기존 stuck 세션 완전 회수 | 이전 봇 세션 종료 + idle pool 복귀 완료 |
| 5 | evidence 보존 완료 | §7 evidence 캡처 + 파일 저장 완료 |

> 회장 명시 (dispatch_conditions.premature_dispatch_forbidden=true): 위 조건 모두 충족 전 재위임 금지.

### 8.4 Retry Count 증가 정책

| 상황 | retry_count 처리 |
|---|---|
| stuck으로 분류된 후 새 세션 재위임 | retry_count += 1 |
| 회귀 픽스 완료 후 재위임 | retry_count 유지 (회귀 픽스는 별도 +1 task) |
| false_positive로 stuck 해제 | retry_count 변경 없음 |

### 8.5 Classification Carry-over 정책

재위임 시 이전 세션의 분류 정보를 새 세션에 전달한다:

- STUCK_AFTER_PR_OPEN + REVIEW_OR_APPROVAL_PENDING_WITH_REGRESSION 분류를 새 세션 초기 컨텍스트에 포함.
- 이전 evidence 파일 경로를 새 세션 briefing에 명시.
- 회귀 지적 17건의 요약을 새 세션 초기 briefing에 포함.

---

## §9 Critical Chain Isolation Rule

**목적**: stuck task가 critical chain 전체를 차단하지 않도록 chain 내 격리 원칙을 정의한다.

### 9.1 task-2487 관련 Critical Chain

task-2487 사건이 영향을 미친 critical chain:

```
task-2486 (완료)
    ↓
task-2485+1 (ESSENCE_PASS / ESCALATED_VERIFIER_LIMITATION — PR #47 머지)
    ↓
task-2487+1 (회귀 픽스 — PR #49/#50/#51 unresolved thread 17건 해소)
    ↓
PR #49 → PR #50 → PR #51 (순차 머지)
    ↓
task-2472+1 (별도 분석 — task-2495-candidate)
    ↓
task-2483 → task-2484
```

task-2487이 stuck으로 분류되면서 chain의 task-2487+1 이후 전 링크가 block 상태가 되었다.

### 9.2 Isolation 원칙

1. **Chain bypass 결정**: stuck task가 critical chain의 다음 link를 물리적으로 차단하는 경우 → 회장이 bypass 경로를 명시 결정. 봇 자동 결정 금지.
2. **Chain pause 결정**: chain 전체를 잠시 멈추고 stuck task 해소를 기다리는 경우 → 회장 명시 결정. 자동 pause 금지.
3. **Critical chain task 자동 stop 금지**: chain 위 task를 detector가 자동으로 stop하면 cascade 위험. 알림만 발송하고 stop은 회장 결정 후 수동 실행.

### 9.3 Critical Chain Task에 대한 Detector 동작 구분

| task 유형 | detector 허용 동작 | detector 금지 동작 |
|---|---|---|
| 일반 task (critical chain 비해당) | STUCK 분류 + .followup 생성 + 세션 회수 후보 등록 | 세션 자동 종료, marker 직접 수정 |
| critical chain task | **알림 발송만** (회장/팀장에게) | 자동 stop, 자동 세션 종료, 자동 chain 재배치 |

### 9.4 ESCALATED_VERIFIER_LIMITATION vs STUCK_AFTER_PR_OPEN 분기 처리

| 발생 상황 | 분류 | 처리 규칙 |
|---|---|---|
| critical chain task에서 ESCALATED_VERIFIER_LIMITATION 발생 (task-2485+1 유형) | ESSENCE_PASS / ESCALATED_VERIFIER_LIMITATION | 본질 PASS이므로 chain 진행. 별도 spec에서 처리. .escalate 마커 보존. |
| critical chain task에서 STUCK_AFTER_PR_OPEN 발생 (task-2487 유형) | STUCK_AFTER_PR_OPEN + REVIEW_OR_APPROVAL_PENDING_WITH_REGRESSION | chain pause 후 회귀 픽스 task(+1) 발행. 원 PR 강제 머지 금지. 회장 명시 결정 대기. |
| 두 유형이 혼동되는 경우 | 즉시 분류 중단 + 회장 알림 | §2.2 구분표로 재판정. false 분류 기록 남기고 수정. |

### 9.5 chain-aware detection 원칙

- critical chain에 속한 task를 감지한 경우 stuck detection report에 "critical_chain: true" 플래그 포함.
- 해당 플래그가 true이면 auto handling Act Step 2 (세션 회수 후보 등록)를 건너뛰고 알림만 발송.
- chain에서의 task 위치(predecessor / successor)도 evidence에 포함.

---

## §10 Implementation Candidates

**목적**: 본 Phase 0 spec에 기반한 실제 구현 후보를 명시한다. 단, 본 task에서 어떠한 코드도 작성하지 않는다. 후속 구현 task 발행 조건과 함께 제안만 한다.

> 회장 명시 (2026-05-08T02:55, phase_b_integration_items §9.4 #5): stuck/zombie detection은 계속 Phase 0 문서화/감사 범위로 유지. 즉시 production 통합 X.

### 10.1 Detector 구현 후보 위치

| # | 후보 경로 | 방식 | 근거 |
|---|---|---|---|
| 1 | `scripts/stuck_detector.py` | 신규 모듈 (done-watcher.py 패턴 차용) | sense/think/act 3분리 구조 독립 구현. 기존 파일 비침습. |
| 2 | `scripts/zombie-watcher.py` | 신규 모듈 (zombie 명칭 사용) | 1시간 이상 무반응 패턴 전문화. stuck과 zombie threshold 분리 가능. |
| 3 | `dispatch.py` 통합 | 기존 파일 보강 | dispatch 흐름 내에서 자연스럽게 stuck 감지 가능. 단, 침습 위험 존재. |
| 4 | `task-timer.py` 통합 | 기존 파일 보강 | timer stale 감지와 결합 가능. --reason stuck 옵션 추가와 동시 구현. |

권장 우선순위: 후보 1 (신규 독립 모듈) → 후보 4 (task-timer.py 통합) 순서로 검토.

### 10.2 Dashboard 통합 후보

- Phase B §2.6 종료 분류별 보드에 STUCK_AFTER_PR_OPEN 섹션 추가.
- 표시 정보: task_id / PR state / unresolved thread 수 / 경과 시간 / evidence 경로.
- MERGE_PENDING_DEPENDENCY 섹션과 유사한 구조로 설계 가능.

### 10.3 Termination Classification Enum 확장 후보

현재 8종 enum (task-2489 TerminationClassification):

```
DONE, ESCALATED, DOGFOODING_PENDING, MERGE_PENDING_DEPENDENCY,
MERGED_CLOSE_BLOCKED_EXTERNAL, BLOCKED_BY_EXTERNAL_DEPENDENCY,
FAILED_PREEXISTING, WAITING_FOR_CHAIR_DECISION (+ UNCLASSIFIED)
```

**추가 검토 후보**: `STUCK_AFTER_PR_OPEN`을 9번째 또는 10번째 분류로 추가.

> 단, 본 task에서 enum을 변경하지 않는다. 후속 구현 task에서 task-2489 TerminationClassification enum 확장을 제안만 한다.

### 10.4 의존 도구 후보

| 도구 | 용도 |
|---|---|
| `gh api repos/.../pulls/{pr}/reviews` | review thread 수집 |
| `gh api graphql` (mergeStateStatus) | PR merge 가능 상태 확인 |
| `member-status.json` | 봇 세션 last activity 조회 |
| `task-timer.py status <task_id>` | timer 경과 시간 조회 |
| lifecycle marker glob | .done / .followup / .escalate / .stuck 존재 여부 |
| `gh api repos/.../rulesets/{id}` | branch protection 설정 조회 |

### 10.5 task-timer.py --reason 확장 후보

현재 `--reason` 옵션에 stuck 전용 분류 추가 필요:

```
# 의사코드 (실제 구현 아님)
python3 memory/task-timer.py end <task_id> --reason stuck_after_pr_open
# → .stuck-after-pr-open 마커 발행, .done 미발행
```

이 옵션이 없으면 stuck task에 부적절하게 `--reason done`이 사용될 위험 존재 (§6 Forbidden Action #1).

### 10.6 후속 구현 Task 발행 조건

> 본 spec 자체는 어떠한 자동 dispatch도 트리거하지 않는다.

후속 구현 task 발행을 위한 선행 조건 (모두 충족 필수):

| # | 조건 | 현재 상태 (2026-05-08 기준) |
|---|---|---|
| 1 | task-2485+1 (PR #47) 머지 완료 | 머지 완료 (ESSENCE_PASS / ESCALATED_VERIFIER_LIMITATION) |
| 2 | task-2487+1 (회귀 픽스) 완료 | 미완료 |
| 3 | PR #49/#50/#51 순차 머지 완료 | 미완료 (BLOCKED) |
| 4 | critical chain 안정화 확인 | 미완료 |
| 5 | 회장 명시 승인 | 미완료 |

위 5개 조건 모두 충족 후 → 회장 명시 승인 → 별도 implementation task 발행.

---

## 부록 A. 관련 문서 경로

| 문서 | 경로 |
|---|---|
| 본 Phase 0 spec | `memory/orchestration/task-2494-phase0-stuck-zombie-detection.md` |
| 후보 spec (JSON) | `memory/events/task-2494-candidate.stuck-detection-spec` |
| Phase B 통합 항목 | `memory/orchestration/phase_b_integration_items_260507.md` |
| ESCALATED_VERIFIER_LIMITATION 분류 | `memory/feedback/feedback_escalated_verifier_limitation_classification_260508.md` |
| task-2487 review 상태 evidence | `memory/events/task-2487.review-or-approval-pending` |
| task-2489 TerminationClassification spec | (task-2489 산출물 경로) |

## 부록 B. 본 task 준수 선언

- 코드/테스트/PR/branch 변경 없음.
- detector 실제 구현 없음.
- task-2487+1 및 오딘 세션 개입 없음.
- admin override / force_push / rebase 없음.
- `.secrets/**` / `.github/workflows/**` / `**/*.py` / `**/*.yml` / `scripts/**` / `tests/**` 수정 없음.
- 후속 구현 task 제안 포함하였으나 실제 구현 없음.
