# P1 옵션 D 구현 — `.work-done` + `.merged` + `.merge-failed` 시맨틱 재설계

## 작업 레벨: Lv.4 (시스템-wide 시맨틱 재설계)

## 프로젝트
- 인프라: `/home/jay/workspace/`
- 핵심 파일: `scripts/finish-task.sh`, `scripts/auto_merge.py`, `scripts/done-watcher.py`, `dispatch.py`, `memory/state/`

## ★ 미팅 근거 (필수 참조)
- 미팅 파일: `memory/meetings/2026-05-02-done-semantics-redesign.md`
- task-2368 보고서: `memory/reports/task-2368.md` (옵션 D 채택)
- DRAFT: `memory/tasks/dispatch-done-semantics-impl-DRAFT.md` (후속 task 2번)

## 배경

### 의존성 (모두 머지 완료)
- task-2364 (P0 Capability Matrix) ✅ `05755351`
- task-2367 (P1 Tiered Auto-Merge) ✅ `9973449f`
- task-2370 (P2 Telegram + Digest) ✅ `9feca90e`
- **task-2371 (P0 핫픽스 fail-closed) ✅ `c0577015` — 본 task 직접 의존**
- task-2368 미팅 옵션 D 채택 ✅

### 현재 결함 (옵션 D가 해결할 것)

`.done` 마커가 봇 작업 끝에 생성되지만 main 머지 미보장. 사례:
- task-2364: `.done` 17:08 → 머지 18:11 (63분 갭, 회장 잘못 보고 사고)

### 미팅 합의 7건 (옵션 D)

1. **3마커 분리**:
   - `.work-done` (declared, finish-task.sh fail-closed 후 생성, P0 핫픽스 적용 완료)
   - `.merged` (observed, done-watcher가 mergedAt 검증 후 atomic 생성)
   - `.merge-failed` (5회 retry 초과)
2. P0 fail-closed 핫픽스 P0 선행 ✅ (task-2371)
3. **state.json SoT**: `memory/state/{task_id}.json` (마커는 캐시, 진실은 state.json)
4. **task.yaml** `kind: code|meta` + `merge_required: bool` 신설 — 시스템·문서 task는 `.work-done` = terminal
5. **Tier별 알림 + dwell 90초**:
   - Tier 1 자동 = `.work-done` 알림 억제 (Daily Digest로 통합)
   - Tier 2/3 수동 = 즉시 알림
   - `.merge-failed` 항상 즉시
6. **12-cell 호환성 회귀** + meta task schema validator + 5회 retry escalation
7. 임시 운영 가드 ✅ (메모리 피드백 추가 완료)

## 작업 범위

### Phase 1 — 마커 분리 + state.json SoT

**1.1 `scripts/finish-task.sh`**
- `.done` 생성 → `.work-done` 생성으로 변경 (의미: "봇 작업 완료")
- `state.json` 신규 생성: `{"task_id": ..., "phase": "work-done", "timestamp": ..., "merge_required": ...}`
- 기존 `.done.merging` 등 transient 마커 보존 (auto_merge.py 사용)

**1.2 `scripts/auto_merge.py` 확장**
- 머지 성공 시 `.merged` 마커 + state.json `phase: "merged"` + `merge_sha` 갱신
- 머지 실패 시 retry counter 증가, 5회 초과 시 `.merge-failed` + state.json `phase: "merge-failed"`
- audit log JSONL에 phase 전이 기록

**1.3 `scripts/done-watcher.py` 확장**
- `.work-done` 감지 시 GitHub mergedAt 폴링 (간격: 60초, 최대 30분)
- mergedAt != null 확인 시 atomic하게 `.merged` 생성 + state.json 갱신
- 30분 초과 시 `.merge-failed` (auto-revert 트리거 P1 산출물 활용)

**1.4 `memory/state/` 디렉토리 + .gitkeep + schema 문서**

### Phase 2 — task.yaml meta 분류

**2.1 task 파일 schema 확장**:
```yaml
allowed_resources: ...  # 기존
kind: code | meta  # 신규
merge_required: true | false  # 신규 (기본값: kind == "code"이면 true)
```

**2.2 `dispatch.py` 파싱**:
- `kind: meta` + `merge_required: false` task는 `.work-done` 생성 시점에 terminal 처리
- state.json `phase: "completed"` 즉시 (mergedAt 폴링 skip)

**2.3 schema validator**:
- task 파일 dispatch 시 schema 검증
- legacy task (kind 미명시) → 기본값 `code` + `merge_required: true`

### Phase 3 — Tier별 알림 + dwell 90초

**3.1 알림 정책**:
- Tier 1 (자동, Lv.0-1) — `.work-done` 즉시 알림 X, Daily Digest 통합 (P2 산출물 재사용)
- Tier 2 (1-tap, Lv.2) — 즉시 inline button (P2 산출물 재사용)
- Tier 3 (회장, Lv.3+) — 즉시 알림 + 대기
- `.merge-failed` 항상 즉시 알림 (별도 채널)

**3.2 dwell 90초**:
- `.work-done` → `.merged` 전이 90초 미만 = "fast track"
- 90초 초과 = "slow track" (회장이 디버깅 진행 알 수 있도록 `.work-done` 시점에 progressive disclosure 알림)

### Phase 4 — 회귀 테스트 + meta validator

**4.1 12-cell 회귀 테스트**:
- 3 phase × 4 시나리오 (정상/실패/timeout/legacy) = 12 케이스
- pytest 신설: `tests/dev7/test_done_semantics.py`

**4.2 meta task schema validator**:
- 신규 task 파일 schema 검증 (kind/merge_required)
- 기존 task 파일 호환성 (legacy 모드)

**4.3 task-2364 사례 재현 시나리오**:
- 봇 작업 끝 → `.work-done` 생성 → 머지 진행 중 → 30분 미만 → `.merged` 생성
- 아누가 `.work-done`을 "머지 완료"로 단정하지 않음 (state.json 검증)

## 검증 시나리오

1. **정상 흐름 (code task)**: `.work-done` → 머지 → `.merged` (90초 내)
2. **slow track (code task)**: `.work-done` → 머지 진행 중 (~5분) → `.merged` (progressive disclosure)
3. **머지 실패 (code task)**: `.work-done` → 5회 retry 실패 → `.merge-failed` + 회장 즉시 알림
4. **meta task**: 미팅/문서 task → `.work-done` = terminal (mergedAt 폴링 skip)
5. **legacy task**: 기존 task 파일 (kind 미명시) → 기본 code + merge_required: true
6. **회귀 0**: P0/P1/P2 모든 흐름 정상 (task-scope-guard, auto_merge tier, audit log, post_merge_probe, auto_revert, anu_confirm_bot, daily_digest)
7. **task-2364 사례 재현**: 옛 .done 패턴 → 새 시맨틱에서는 `.merged` 생성 시점에만 "머지 완료" 인지

## affected_files

### 신규
- `memory/state/.gitkeep`
- `memory/specs/done-semantics-state-schema.md`
- `tests/dev7/test_done_semantics.py`
- `tests/dev7/test_meta_task_validator.py`

### 수정
- `scripts/finish-task.sh` (`.done` → `.work-done` + state.json 생성)
- `scripts/auto_merge.py` (`.merged` 생성 + retry counter)
- `scripts/done-watcher.py` (mergedAt 폴링 + atomic `.merged` 생성)
- `dispatch.py` (task.yaml `kind`/`merge_required` 파싱)
- `memory/specs/bot-capability-model.md` (state.json 추가)

### 변경 금지
- `scripts/task-scope-guard.sh` (P0 산출물 회귀 0)
- `scripts/post_merge_probe.py` (P1 산출물)
- `scripts/auto_revert.py` (P1 산출물)
- `scripts/anu_confirm_bot/**` (P2 산출물)
- `scripts/daily_digest.py` (P2 산출물)
- `memory/audit/auto-merge.log` (read-only)
- `memory/capabilities/**`
- `CLAUDE.md` (5대 규칙 보존)
- `memory/plans/bot-capability-system/{plan,context-notes}.md` (P0 결정 보존)

## allowed_resources

```yaml
allowed_resources:
  paths:
    - "scripts/finish-task.sh"
    - "scripts/auto_merge.py"
    - "scripts/done-watcher.py"
    - "dispatch.py"
    - "memory/state/**"
    - "memory/specs/done-semantics-state-schema.md"
    - "memory/specs/bot-capability-model.md"  # state.json 추가만
    - "tests/dev7/test_done_semantics.py"
    - "tests/dev7/test_meta_task_validator.py"
    - "memory/plans/tasks/task-XXXX/**"
    - "memory/plans/bot-capability-system/checklist.md"  # 진행 체크
  forbidden_paths:
    - "scripts/task-scope-guard.sh"
    - "scripts/post_merge_probe.py"
    - "scripts/auto_revert.py"
    - "scripts/anu_confirm_bot/**"
    - "scripts/daily_digest.py"
    - "memory/audit/**"
    - "memory/capabilities/**"
    - "CLAUDE.md"
    - "memory/plans/bot-capability-system/plan.md"
    - "memory/plans/bot-capability-system/context-notes.md"
    - ".github/**"
  commands:
    - "pytest"
    - "python3 -m py_compile"
    - "bash scripts/finish-task.sh"
    - "gh pr view"
  merge_policy: "tiered"  # Lv.4 → Tier 3 회장 명시 승인 필수
  ttl_hours: 96
```

## 작업 원칙
- **Think Before Coding**: state machine 다이어그램 사전 작성 (`.work-done` → `.merged`/`.merge-failed`)
- **Simplicity First**: state.json schema는 필수 필드만
- **Surgical Changes**: P0/P1/P2 산출물 절대 회귀 0
- **Goal-Driven**: `.merged` = 실제 main 머지 보장 (task-2364 사례 차단)

## 보고

- `memory/reports/task-XXXX-done-semantics-option-d.md`
- 7가지 검증 시나리오 PASS/FAIL 매트릭스
- state.json schema 문서
- 12-cell 회귀 테스트 결과
- task-2364 사례 시뮬레이션 차단 결과
- legacy task 호환성 통계 (몇 건이 자동 마이그레이션 되는지)

## 운영 메모

### 의존성
- 모든 P0/P1/P2 + P0 핫픽스 머지 완료 ✅
- 다른 활성 task와 영역 충돌 0 (다른 봇 모두 유휴)

### 워크트리
- ★ 워크트리 필수 (`.worktrees/task-XXXX-dev7`)

### 위임 후보
- **dev7 (이참나)** — task-2360/2364/2367/2371 모든 컨텍스트 보유 (인프라 일관성)

### 회장 승인 게이트
- ★ 본 task는 **Lv.4 시스템-wide** + **모든 finish-task/auto_merge/dispatch 동시 변경** → Tier 3 회장 명시 승인 필수
- 본 task가 머지되면 임시 운영 가드(`feedback_merge_status_cross_verify.md`)는 secondary verification으로 격하 가능

### finish-task.sh
- ⚠️ 본 task가 finish-task.sh 자체 수정 → 자기 호출 시 회귀 주의
- task-2371 P0 핫픽스 적용 후이므로 fail-closed 동작 검증됨
- 본 task의 finish-task.sh 호출은 *수정 후 새 시맨틱*으로 실행됨

### 후속 task
- **task-237Y (P2 안정화)**: 본 task 머지 후 별도 위임 (DRAFT 후속 3번)
- **task-237Z (Dashboard 시각화)**: P2 안정화 후

## 참조

- 미팅 파일: `memory/meetings/2026-05-02-done-semantics-redesign.md`
- task-2368 보고서: `memory/reports/task-2368.md`
- DRAFT: `memory/tasks/dispatch-done-semantics-impl-DRAFT.md`
- task-2364 사례 (.done 17:08 → 머지 18:11)
- task-2371 P0 핫픽스 (`c0577015`)
- 메모리 피드백: `feedback_merge_status_cross_verify.md` (임시 운영 가드)