---
task_id: task-2518
type: plan
scope: task
created: 2026-05-09
updated: 2026-05-09
status: in-progress
---

# 계획서: task-2518 — lifecycle_reconciliation_manager

**task**: task-2518
**목표**: bot session ↔ task lifecycle 결합 제거 + GitHub/CI/smoke evidence를 source-of-truth로 사용하는 idempotent reconcile state machine 구축
**승인**: 회장 2026-05-09 직접 — Phase 2 P1 진입
**근거**: memory/tasks/task-2518.md (회장 명시 7 사례 + 8 stuck case)

---

## 목표

`utils/lifecycle_reconciliation_manager.py` (NEW) + `tests/regression/test_lifecycle_reconciliation_manager_2518.py` (NEW) 정확히 2 파일을 추가하여 다음을 보장한다:

1. **LifecycleState enum 7종** (RUNNING / PR_OPEN / MERGED_PENDING_RECONCILE / RECONCILING / FINALIZED / STUCK_NEEDS_RECONCILE / ESCALATED)
2. **source-of-truth reconcile**: PR state + mergeCommit + origin/main 포함 + CI status + smoke + task-timer + file marker (file marker는 derived)
3. **stuck detection 8 케이스** 자동 감지 (회장 §1~7 + Telegram cut-off)
4. **idempotent reconcile loop** (반복 호출 → 동일 state)
5. **manual .done 위장 차단** (evidence 없는 강제 .done 생성 시 RuntimeError)
6. **CLI**: `--task-id <id> --reconcile [--apply]`, `--scan-stuck [--apply]`
7. **CanonicalWorkspace + automation_contracts 연동** (변경 0건)

## 범위

### 포함
- `utils/lifecycle_reconciliation_manager.py` 신규 작성
- `tests/regression/test_lifecycle_reconciliation_manager_2518.py` 14건 회귀 작성
- replay fixture 5건 (task-2517 dev2 cut-off, PR merged + .done 없음, mergeCommit + timer running, finish-task 중단, repeated reconcile)

### 제외 (다음 페이즈 이후)
- dispatch.py 수정 (금지)
- finish-task.sh rewrite (금지)
- 5 모듈 본체 수정 (금지)
- canonical_workspace_resolver / automation_contracts 변경 (금지)
- repository_policy_adapter (task-2519)
- live pilot (task-2520)

## 위임 계획

- 설계 + 인터페이스 정의: **다그다(팀장)** — 직접 (Plan 모드, 코딩 X)
- `utils/lifecycle_reconciliation_manager.py` 구현: **루(백엔드)** — Sonnet (lifecycle state machine은 백엔드 핵심 로직)
- `tests/regression/test_lifecycle_reconciliation_manager_2518.py` 구현: **모리건(테스터)** — Sonnet (회귀 테스트는 테스터 도메인)
- 통합/검토: **다그다(팀장)** — 직접

## 검증 기준

- 회귀 14/14 PASS: `cd .worktrees/task-2518-dev3 && python3 -m pytest tests/regression/test_lifecycle_reconciliation_manager_2518.py -v`
- replay fixture 5건 PASS (회귀 안에 포함)
- repeated reconcile deterministic PASS
- effective diff = 정확히 2 파일: `git diff --name-only origin/main` → 정확히 expected_files
- L1 스모크: `python3 utils/lifecycle_reconciliation_manager.py --task-id task-2517 --reconcile` (dry-run, evidence read-only)
- 5 모듈 본체 / canonical_workspace_resolver / automation_contracts / dispatch.py / finish-task.sh 변경 0건
- Codex G1 사전 검증 PASS
- Gemini PR 리뷰 PASS (High 0건)

## 3 Step Why

**1st Why: 왜 이 설계가 필요한가?**
A: 봇 세션 종료 / Telegram cut-off / finish-task 중단으로 task lifecycle이 불일치 상태에 빠지는데, file marker만 보고 판단하면 evidence가 부정확하다. GitHub/CI evidence를 source-of-truth로 두고 file marker는 derived로 취급해야 reconcile이 결정적이 된다.

**2nd Why: 왜 source-of-truth + idempotent state machine이 최선의 접근인가?**
B: (대안 1) "manual .done 강제 생성"은 evidence 위장이라 회장이 명시 금지. (대안 2) "dispatch.py에 lifecycle 로직 통합"은 dispatch.py 대규모 수정 금지. (대안 3) "5 모듈 안에 reconcile 추가"는 본체 수정 금지. → 별도 모듈 + dry-run apply 분리 + GitHub evidence 우선이 유일하게 회장 금지 사항을 위반하지 않는 경로다.

**3rd Why: 왜 별도 모듈 + dry-run apply 분리가 다른 대안보다 나은가?**
C: dry-run은 안전성(side effect 0)을 보장하고, evidence 기반 backfill은 위장이 아니라 lifecycle complete를 사실 그대로 반영. CanonicalWorkspace + automation_contracts를 import만 하므로 contract schema 변경 0. expected_files 정확히 2 파일이라 Merge Topology Gate 자기참조 PASS.

→ A-B-C 일관성 PASS.
