# task-2489 — Phase B 8종 종료 분류 enum + 자동 분류 룰 설계

- 팀: dev6-team (페룬 / 스바로그 / 모코시 / 벨레스)
- 레벨: Lv.3 (시스템 청사진 + dry-run 코드)
- 상태: ✅ 완료
- 일시: 2026-05-08

---

## S — Situation (상황)

Phase A 운영에서 종료 분류가 `DONE` / `ESCALATED` 2종에 그쳐, 본질 PASS인데 외부 의존(BOT 토큰, 후속 task, workspace dirty 등)으로 lifecycle close가 막힌 6종 케이스가 모두 ESCALATED로 잘못 박제. retry 룰이 본질 재작업을 시도해 무의미한 사이클이 발생. task-2472+1 (4시간 stale), task-2481 (BOT 토큰 401), task-2483 (post-merge close FAIL) 3건이 동일 패턴.

회장은 phase_b_integration_items_260507.md에 8종 분류 enum + 자동 분류 룰 + task-timer.py `--reason` 옵션을 명시했고, 본 task는 그 청사진을 명세 + dry-run classifier로 구현하되 **production 미반영(task-2486 머지 후 회장 재결정)**을 강조함.

## C — Complication (문제)

1. task-timer.py 결함: 모든 종료에 `.done` 자동 생성 → MERGE_PENDING_DEPENDENCY 케이스에 회장 금지 #1 위반.
2. 8종 분류 우선순위 / 충돌 해결 룰 부재.
3. 마커 파일 컨벤션 표준 부재 (분류별 파일명 / 부가 .conditions 미정의).
4. dispatch.py 후속 트리거(의존 task .done 감지 → CI rerun → .done 변환 등) 미구현.
5. 회귀 검증 fixture 부재 — 분류 정확도 측정 불가.
6. **격리 제약**: task-timer.py / dispatch.py / scripts/* / utils/* 일체 수정 금지 (회장 명시).

## Q — Question (질문)

> 8종 분류 enum + 자동 분류 룰 + dry-run classifier + 회귀 fixture를 격리 경로에 어떻게 작성하면, 회장이 task-2486 머지 후 production 반영 결정을 데이터 기반으로 내릴 수 있는가?

## A — Answer (해답 + 산출물)

### 1. 분류 룰 설계 문서 (모코시)

`memory/orchestration/phase_b_termination_classifier_spec_260508.md` (654줄)

- 8종 분류 enum 정의 (DONE / ESCALATED / DOGFOODING_PENDING / MERGE_PENDING_DEPENDENCY / MERGED_CLOSE_BLOCKED_EXTERNAL / BLOCKED_BY_EXTERNAL_DEPENDENCY / FAILED_PREEXISTING / WAITING_FOR_CHAIR_DECISION)
- 발동 조건 boolean expression (분류별 ALL/ANY)
- 우선순위 9단계 decision tree + 동시 매칭 충돌 해결
- 마커 파일 컨벤션 표 (분류 → 마커 파일명 + 부가 .conditions + 차단 동작)
- 자동 트리거 매트릭스 (분류 → 자동 액션 / dispatch.py 트리거 / 사람 개입 여부)
- task-timer.py `--reason` 옵션 명세 (문서만, 코드 X)
- 회귀 fixtures 5종 매핑
- production 반영 결정 (회장 재결정 영역) 명시
- Codex 사전 검증 결과 반영 (섹션 11)

### 2. dry-run classifier (스바로그)

`tools/poc/termination_classifier.py` (441줄, 격리)

- `TerminationClassification` enum (8종 + UNCLASSIFIED 안전망)
- `TaskEvidence` dataclass (모든 입력 필드, 안전 default)
- `ClassificationResult` dataclass (classification, confidence, matched_rule, marker_file, preserve_markers, followup_conditions, notes)
- `classify(evidence)` — 9개 룰 우선순위 평가 → 첫 매칭 결과 반환
- CLI dry-run: `python3 tools/poc/termination_classifier.py <fixture.json>` → JSON 출력
- **dry-run 보장**: dataclass 반환만, 마커 파일 생성 / dispatch 호출 / 네트워크 호출 0건

### 3. 회귀 fixtures + 테스트 (벨레스)

`memory/poc/termination_classifier/fixtures/`:
- `task-2466.json` → DONE
- `task-2481.json` → DOGFOODING_PENDING
- `task-2472+1.json` → MERGE_PENDING_DEPENDENCY
- `task-2483.json` → MERGED_CLOSE_BLOCKED_EXTERNAL
- `task-2485.json` → MERGE_PENDING_DEPENDENCY (가정 시나리오, 회귀 신뢰도: 낮음)

`tests/poc/test_termination_classifier.py`:
- 5종 회귀 (parametrize) PASS
- 우선순위 충돌 (DONE > DOGFOODING_PENDING) PASS
- 부정 테스트 (false-positive 방지) PASS
- 부수효과 검증 (`monkeypatch.chdir(tmp_path)` 후 파일 0개 생성) PASS
- **15/15 PASSED**

### 4. task-timer.py `--reason` 옵션 명세 (문서만)

명세 섹션 7에 시그니처 + 분류별 동작 명시.
**production 코드 0 변경** — Phase B 진입 시 회장 결정으로 적용.

---

## 검증

### 셀프 QC 8항목

| # | 항목 | 결과 |
|---|---|---|
| 1 | 산출물 합격 조건 충족 | ✅ 4종 전부 (spec / classifier / fixtures / --reason 명세) |
| 2 | production 파일 0 변경 | ✅ task-timer.py / dispatch.py / scripts/* / utils/* 미수정 |
| 3 | 회귀 테스트 PASS | ✅ pytest 15/15 PASS |
| 4 | dry-run 보장 | ✅ classifier 부수효과 0 (test_dry_run_no_side_effects) |
| 5 | 마커 파일 미생성 | ✅ events/task-2489.{done,escalate,merge-pending,...} 0건 |
| 6 | Codex 사전 검증 PASS | ✅ pass=true, 심각도 플래그=false, high 2건 보강 완료 |
| 7 | 3문서 업데이트 | ✅ plan/context-notes/checklist 모두 status=completed |
| 8 | 보고서 SCQA 4섹션 | ✅ Situation/Complication/Question/Answer 작성 |

### Codex 사전 검증 결과 (`memory/events/task-2489.codex-gate`)

- pass: **true**
- 심각도 플래그: **false** (severe risk 0건)
- risks: 6건 (high 2 / medium 3 / low 1)
- **High 2건 보강 완료**:
  - DONE 룰: `essence_verdict == PASS` + `pr_merged_at IS NOT NULL` + `forbidden_violations == 0` 추가
  - MERGE_PENDING_DEPENDENCY 룰: `pr_merged_at IS NULL` + `done_marker_exists == False` + `ci_fail_owner == EXTERNAL_DEPENDENCY` 추가
  - BLOCKED_BY_EXTERNAL_DEPENDENCY / FAILED_PREEXISTING 룰: `pr_state in (None, "OPEN")` 추가
- **Medium 3건 명세 반영**: UNCLASSIFIED 정합성 (섹션 9), task-2485 fixture 신뢰도 (섹션 8 비고), 섹션 11 검증 결과
- **Low 1건**: Phase B 운영 데이터 축적 후 부정 테스트 보강 — 본 task에서도 6건 추가 PASS

### L1 스모크테스트 결과

- **서버 재시작**: 해당없음 (격리 POC, server 무관)
- **API 응답 확인**:
  - `python3 tools/poc/termination_classifier.py memory/poc/termination_classifier/fixtures/task-2466.json` → classification: DONE, confidence: 1.0, matched_rule: R1_DONE
  - `python3 tools/poc/termination_classifier.py memory/poc/termination_classifier/fixtures/task-2483.json` → classification: MERGED_CLOSE_BLOCKED_EXTERNAL, confidence: 1.0, matched_rule: R2_MERGED_CLOSE_BLOCKED_EXTERNAL
  - 위 두 결과 모두 `dry_run: true` 마커 + 마커 파일 미생성 확인
- **스크린샷**: 해당없음 (CLI/문서 작업)
- **격리 검증**: `git status --short memory/task-timer.py scripts/dispatch.py scripts/finish-task.sh` → 변경 없음

### 마아트 독립 검증

본 task는 격리 POC + 명세 문서. 마아트 독립 검증은 다음 시점에 수행 권장:
- Phase B 진입 시 (production 반영 결정 후) — task-timer.py `--reason` 옵션 추가 PR
- 본 task 자체는 production 영향 0 → 마아트 검증 우선순위 낮음 (보고서에 명시)

---

## 생성/수정 파일 목록

### 생성 (격리 경로)
- `memory/orchestration/phase_b_termination_classifier_spec_260508.md` (654줄)
- `tools/poc/termination_classifier.py` (441줄)
- `tests/poc/__init__.py` (신규)
- `tests/poc/conftest.py` (신규, sys.path 등록)
- `tests/poc/test_termination_classifier.py` (15 테스트)
- `memory/poc/termination_classifier/fixtures/task-2466.json`
- `memory/poc/termination_classifier/fixtures/task-2481.json`
- `memory/poc/termination_classifier/fixtures/task-2472+1.json`
- `memory/poc/termination_classifier/fixtures/task-2483.json`
- `memory/poc/termination_classifier/fixtures/task-2485.json`

### 업데이트 (3문서)
- `memory/plans/tasks/task-2489/plan.md` (status: draft → completed)
- `memory/plans/tasks/task-2489/context-notes.md` (3 Step Why + 결정 근거)
- `memory/plans/tasks/task-2489/checklist.md` (전 항목 [x])

### 수정 금지 항목 (회장 명시) — 0 변경 확인
- ❌ `memory/task-timer.py`
- ❌ `scripts/dispatch.py` / `scripts/taskctl.py` / `scripts/finish-task.sh` / `scripts/refresh_bot_token.py`
- ❌ `utils/task_id_parser.py` / `utils/state_repair.py` / `utils/g3_fail_classifier.py`
- ❌ `teams/**` / `.github/workflows/**`

---

## 머지 판단

- **머지 필요**: No (worktree 미사용. 직접 commit, 격리 경로만)
- **브랜치**: main (직접 커밋, ref: 본 commit)
- **머지 의견**: 격리 경로 산출물만 추가. production 영향 0. task-2486 머지 후 회장이 `--reason` 옵션을 task-timer.py에 적용할지 재결정 영역.

---

## 발견 이슈 및 해결

1. **Pyright LSP stale 진단** (test_termination_classifier.py import error)
   - 명령행 pyright는 `0 errors` (pyrightconfig.json extraPaths 정상)
   - LSP 캐시가 conftest.py / __init__.py 새로 추가된 파일을 보지 못함
   - 해결: 테스트 파일 헤더에 `# pyright: reportMissingImports=false` + 사유 주석
   - 실 영향 없음 (pytest 15/15 PASS, 명령행 pyright 0 errors)

2. **Codex high 2건 (DONE / MERGE_PENDING_DEPENDENCY 룰 느슨)**
   - 스바로그가 즉시 보강 (TaskEvidence 3개 필드 추가 + 룰 4개 강화)
   - 벨레스가 fixture 보강 (task-2472+1 / task-2485에 ci_fail_owner / done_marker_exists 추가)
   - 결과: 15/15 PASS 유지

3. **dogfooding feedback 파일 위치 분리**
   - workspace/memory/feedback/에 dogfooding 파일 없음
   - `~/.claude/projects/-home-jay--cokacdir-workspace-autoset/memory/`에 존재
   - 모코시가 후자 경로로 참조하여 명세 작성 — 본 task 영향 없음

---

## 모델 사용 기록

| 팀원 | 모델 | 작업 | 정당성 |
|---|---|---|---|
| 페룬 (팀장) | Opus 4.7 | 설계 분배 / Codex 검증 / 통합 / 보고서 | 판단 / 검토 / 통합 (Opus 토큰 정당) |
| 모코시 (UX/UI) | sonnet | 654줄 명세 문서 작성 | 정보 설계 + 의사결정 트리, sonnet 적합 |
| 스바로그 (백엔드) | sonnet | 441줄 classifier + 룰 보강 | Python dataclass / 룰 엔진, sonnet 적합 |
| 벨레스 (테스터) | sonnet | 15 테스트 + 5 fixture | 회귀 검증 + edge case, sonnet 적합 |

haiku 사용 0건 (전략/명세/검증 작업 — sonnet 이상 필요).

---

## 다음 단계 (회장 재결정 영역)

1. **task-2486 머지 완료** 대기
2. 본 명세 + dry-run classifier 검증 결과 회장 검토
3. production 반영 결정 시 단계:
   - (1) `task-timer.py end --reason <classification>` 옵션 추가 (단독 PR)
   - (2) dispatch.py 자동 트리거 (의존 task .done 감지 → CI rerun → 마커 변환)
   - (3) 대시보드 7섹션 보드
   - 각 단계 회장 승인 게이트
4. UNCLASSIFIED 운용 방안 회장 결정 (WAITING_FOR_CHAIR_DECISION 흡수 vs 별도 보존)
5. task-2485 fixture 실증 데이터 확보 또는 회귀 세트에서 제외 결정

---

## 비고

- 본 task는 **시스템 청사진**이며 코드는 **격리 dry-run only**.
- production 영향 0 → 머지 즉시 영향 없음.
- 회장 명시 6대 금지(task-timer.py 수정, dispatch 호출, marker 생성, admin override 등) 모두 준수.
- 헤르메스/아누 통합 요약 경유 보고. 회장 직접 장문 보고 X.
