# task-2518 — lifecycle_reconciliation_manager (P0 — bot session ↔ task lifecycle 분리)

- 작업 유형: **runtime infrastructure hardening + 회귀 테스트** (정책 문서 X)
- 작업 레벨: **Lv.3+** (시스템 lifecycle state machine)
- 우선순위: **★★★ P0**
- Track: **lifecycle_reconciliation / bot_session_decoupling / source_of_truth_recovery / phase2_p1**
- parallel_policy: **limited_parallel** (회장 명시 parallel_safe — gate enum 호환은 limited_parallel)
- 일시: 2026-05-09
- 회장 결정: 2026-05-09 직접 — Phase 2 P1 진입

## ⚠️ 본 task의 본질 — 회장 명시

> 현재 운영에서 확인된 문제는 **기능 부족이 아니라 runtime lifecycle determinism 부족**.
>
> task lifecycle을 **recoverable + idempotent state machine**으로 표준화한다.
> **봇 세션과 task lifecycle을 분리**한다.
>
> 봇이 중간에 죽거나 Telegram 송신이 끊겨도, **GitHub/CI/smoke/evidence를 source-of-truth**로 사용해
> task 상태를 자동 reconcile 가능해야 한다.

## 시스템 상태

- ✅ **CODE_AUTOMATION_SYSTEM_PHASE_1_COMPLETE** + Phase 2 P0 (task-2517 canonical_workspace_resolver)
- ✅ task-2516+1 (W1 default 활성화) MERGED
- 🟡 **Phase 2 P1 시작** — task-2518 (lifecycle) + task-2519 (repository policy) 병렬
- 🔒 task-2520 live pilot은 task-2518 + task-2519 모두 main 머지 완료 후

## 회장 명시 7 사례 (구조적 제거 대상)

1. PR은 이미 merged인데 .done/.merge-done/finalize 누락
2. Telegram reply cut-off 이후 task running처럼 남음 (task-2517 dev2 사례)
3. finish-task 중단 후 lifecycle ambiguity
4. mergeStateStatus BLOCKED 원인 분류 불명확 (→ task-2519 영역)
5. repository ruleset / required_review_thread_resolution / runtime capability 판단 부족 (→ task-2519 영역)
6. 회장 직접 머지를 fallback처럼 요청하는 흐름
7. bot session 종료와 task lifecycle 결합

## dependency

- ✅ task-2509.merged
- ✅ task-2509+2.merged (automation_contracts.py)
- ✅ task-2514.merged (5 모듈 wiring)
- ✅ task-2517.merged (canonical_workspace_resolver, mergeCommit `4d45947e`)

## Merge Topology Gate metadata

```yaml
expected_files:
  - "utils/lifecycle_reconciliation_manager.py"  # NEW
  - "tests/regression/test_lifecycle_reconciliation_manager_2518.py"  # NEW

risk_area: "lifecycle_state_machine / bot_session_decoupling / source_of_truth / idempotent_reconcile"

dependency:
  - "task-2509.merged"
  - "task-2509+2.merged"
  - "task-2514.merged"
  - "task-2517.merged"

parallel_policy: "limited_parallel"

merge_queue_position: 16

stale_recheck_required: true

cherry_pick_allowed: false
```

## 필수 구현

### 1. lifecycle state enum (7종)

```python
class LifecycleState(str, Enum):
    RUNNING                       # task-timer running, 작업 진행 중
    PR_OPEN                       # PR 생성됨, 머지 대기
    MERGED_PENDING_RECONCILE      # PR merged, finalize 누락 (회장 §1 사례)
    RECONCILING                   # reconcile 진행 중
    FINALIZED                     # .done.acked + .merge-done + timer end 모두 정상
    STUCK_NEEDS_RECONCILE         # stuck 자동 감지
    ESCALATED                     # Critical 7종 발동
```

### 2. source-of-truth reconciliation

다음 evidence 조합으로 lifecycle 결정 (file system은 derived):
- PR state (gh pr view)
- mergeCommit
- origin/main 포함 여부 (git log --grep / merge-base)
- CI status
- smoke result (PostMergeSmokeRun envelope)
- task-timer (memory/task-timers.json)
- .done / .merge-done / qc-result / followup/escalate marker

**규칙**: file marker가 없어도 GitHub/CI evidence가 충분하면 finalize 가능.

### 3. stuck detection (8 케이스)

자동 감지:
1. **task-timer running인데 PR merged** (회장 §2)
2. **PR merged인데 .done 없음** (회장 §1)
3. **mergeCommit 존재하지만 .merge-done 없음** (회장 §1)
4. **CI/smoke PASS인데 finalize 안 됨**
5. **Telegram reply cut-off** (cron history 마지막 응답이 잘린 상태로 종료)
6. **bot session 종료** (cron status=cancelled/error지만 task evidence는 정상)
7. **finish-task 중단** (worktree 존재 + branch push 완료 + PR 미생성)
8. **stale escalate marker** (escalate 표시 후 N분 경과 + Critical 7종 매칭 안 됨)

### 4. idempotent reconcile loop

같은 reconcile을 여러 번 실행해도 상태 안정:
- 이미 FINALIZED → no-op
- merged + smoke PASS → finalize 가능 (`.done.acked` + `.merge-done` backfill + timer end)
- timer running + PR MERGED → timer 종료 (evidence 기반)
- evidence 충분 → minimal backfill (필요 marker만 생성, 위장 X)

### 5. manual .done 위장 금지

- ★ 사람이 fake `.done` 찍는 방식 금지
- 반드시 evidence 기반 lifecycle finalize만 허용
- backfill 시 evidence source / timestamp / mergeCommit 명시 필수

### 6. CanonicalWorkspace + automation_contracts 연동

- import: `from utils.canonical_workspace_resolver import resolve_canonical_workspace, CanonicalWorkspace`
- import: `from utils.automation_contracts import AutomationDecision, EscalationPacket, CriticalEscalationType`
- 본 task에서 contract schema 변경 0

### 7. CLI entrypoint

```
python3 utils/lifecycle_reconciliation_manager.py --task-id <id> --reconcile [--apply]
python3 utils/lifecycle_reconciliation_manager.py --scan-stuck [--apply]
```
- 출력: `LifecycleReport` JSON (state + stuck reason + evidence + actions taken)
- `--apply` 없이는 dry-run

## 필수 회귀 테스트 14건

`tests/regression/test_lifecycle_reconciliation_manager_2518.py`:

### state enum + reconciliation (4건)
1. lifecycle state enum 7종 정확 매칭
2. source-of-truth: merged + smoke PASS → FINALIZED 가능 판정
3. source-of-truth: timer running + PR OPEN → RUNNING 유지
4. evidence 충돌 시 GitHub > timer 우선

### stuck detection 8 케이스 (8건 — 회장 §1~7 + Telegram cut-off)
5. **timer running + PR merged** (회장 §2 task-2517 dev2 사례)
6. **PR merged + .done 없음** (회장 §1)
7. **mergeCommit 존재 + .merge-done 없음** (회장 §1)
8. **CI/smoke PASS + finalize 미완**
9. **Telegram reply cut-off** (cron history 사례)
10. **bot session 종료** (cron error + task evidence 정상)
11. **finish-task 중단** (worktree + branch push + PR 미생성)
12. **stale escalate marker** (Critical 7종 미매칭)

### idempotent + manual .done 금지 (2건)
13. **repeated reconcile idempotent**: 동일 reconcile 3회 호출 → state 동일, no-op
14. **manual .done 위장 차단**: evidence 없는 `.done` 강제 생성 시도 → RuntimeError

## replay fixture (회장 명시 — 반드시 replay)

회귀 테스트 안에 다음 실제 사례 fixture 포함:
- task-2517 dev2 Telegram reply cut-off (cron `2BAB8982` 마지막 "Pr"로 잘림)
- PR merged but .done missing (회장 §1)
- mergeCommit exists but timer running
- finish-task interrupted
- repeated reconcile idempotency

## 금지 행위 (회장 명시 — 절대 준수)

- **dispatch.py 대규모 수정 금지**
- **finish-task.sh 전체 rewrite 금지**
- **정책 문서만 작성 금지**
- **manual .done 생성 금지** (★ evidence 기반만)
- **5 모듈 본체 수정 금지** (merge_queue_executor / replacement_pr_runner / auto_gemini_triage / post_merge_smoke_runner / critical_escalation_reporter)
- **canonical_workspace_resolver 수정 금지** (READ ONLY)
- **automation_contracts 변경 금지**
- **task-2519 영역 침범 금지** (repository policy adapter는 task-2519)
- **force push / rebase / admin override 금지**
- **required CI bypass 금지**
- **PR #52/#49/#50/#51 수정 금지**
- **expected_files 외 수정 금지** (정확히 2 파일)
- **자동 cherry-pick 구현 금지**
- **live pilot 직접 시도 금지** (task-2520 영역)
- **Critical 7종 외 회장 보고 금지**
- **amendment 무시 / mid-dispatch correction 무시 금지**

## allowed_resources

```yaml
allowed_resources:
  read_only_paths:
    - "memory/tasks/task-2509*"
    - "memory/tasks/task-2510*"
    - "memory/tasks/task-2511*"
    - "memory/tasks/task-2512*"
    - "memory/tasks/task-2513*"
    - "memory/tasks/task-2514*"
    - "memory/tasks/task-2515*"
    - "memory/tasks/task-2516*"
    - "memory/tasks/task-2517*"
    - "memory/tasks/task-2518*"
    - "memory/feedback/feedback_critical_escalation_only_260508.md"
    - "utils/automation_contracts.py"
    - "utils/canonical_workspace_resolver.py"
    - "utils/merge_queue_executor.py"
    - "utils/replacement_pr_runner.py"
    - "utils/auto_gemini_triage.py"
    - "utils/post_merge_smoke_runner.py"
    - "utils/critical_escalation_reporter.py"
    - "utils/merge_topology_gate.py"
    - "memory/orchestration-audit/merge-queue.jsonl"
    - "memory/task-timers.json"
    - ".env.keys"
  paths:
    - "memory/tasks/task-2518*"
    - "memory/reports/task-2518*"
    - "memory/events/task-2518*"
    - "utils/lifecycle_reconciliation_manager.py"  # NEW
    - "tests/regression/test_lifecycle_reconciliation_manager_2518.py"  # NEW
  forbidden_actions:
    - "dispatch.py 대규모 수정"
    - "finish-task.sh 전체 rewrite"
    - "정책 문서만 작성"
    - "manual .done 생성"
    - "5 모듈 본체 수정"
    - "canonical_workspace_resolver 수정"
    - "automation_contracts 변경"
    - "task-2519 영역 침범 (repository_policy_adapter)"
    - "force push"
    - "rebase"
    - "admin override (gh pr merge --admin)"
    - "required CI bypass"
    - "PR #52/#49/#50/#51 수정"
    - "expected_files 외 수정"
    - "자동 cherry-pick 구현"
    - "live pilot 직접 시도"
    - "Critical 7종 외 회장 보고"
    - "amendment 무시 / mid-dispatch correction 무시"
```

## 완료 조건 (회장 명시)

1. ✅ 실행 가능한 Python 코드 (`utils/lifecycle_reconciliation_manager.py`)
2. ✅ 회귀 14/14 PASS
3. ✅ replay fixture PASS (5 사례)
4. ✅ repeated reconcile deterministic PASS
5. ✅ Critical 7종 외 회장 보고 0건
6. ✅ Merge Topology Gate 자기참조 PASS (effective diff = 정확히 2 파일)
7. ✅ CI 11/11 SUCCESS
8. ✅ 5 모듈 본체 / canonical_workspace_resolver / automation_contracts / dispatch.py / finish-task.sh 변경 0건
9. ✅ amendment 보호 의무 명시 + 적용 evidence

## 후행 (회장 명시)

본 task + task-2519 모두 main 머지 완료 후:
- **task-2520** — low-risk live pilot
- **task-2521** — automation observability/dashboard

## affected_files
- utils/lifecycle_reconciliation_manager.py (NEW)
- tests/regression/test_lifecycle_reconciliation_manager_2518.py (NEW)