---
task_id: "dispatch-done-semantics-impl-DRAFT"
status: DRAFT
team: "TBD (1팀+7팀 협업 권장)"
level: 3
priority: P0
depends_on: []
created_at: 2026-05-02
deadline: null
spec_doc: "memory/meetings/2026-05-02-done-semantics-redesign.md"
tags:
  - draft
  - done-semantics
  - awaiting-chairman-approval
---

# `.done` 시맨틱 재설계 구현 — 후속 task 초안 (DRAFT)

> ⚠️ **DRAFT 상태**. 본 파일은 task-2368 미팅 결과를 기반으로 작성된 **후속 task 초안**입니다.
> 회장 명시 승인 후 아누(개발실장)가 정식 task 번호로 dispatch합니다.

## 미팅 근거

- 미팅 파일: `memory/meetings/2026-05-02-done-semantics-redesign.md`
- task-2368 보고서: `memory/reports/task-2368.md`
- 채택 옵션: D (하이브리드) — `.work-done` + `.merged` + `.merge-failed` + state.json SoT

## 후속 task 분할 (3개 권장)

### 후속 task 1 — P0 핫픽스 (별도 PR, 즉시 dispatch 가능)

**가칭**: task-2369-finish-task-fail-open-hotfix
**팀**: 1팀(헤르메스) 또는 7팀(이참나) — `scripts/` 수정 권한 있는 팀
**레벨**: Lv.2 (격리 단일 PR)
**우선순위**: P0
**의존**: 없음 (옵션 D 구현 독립)

#### 작업 범위
1. `scripts/finish-task.sh` 라인 434-438, 940-959 수정:
   - `worktree_manager.py finish --action auto` exit code 검사 강제
   - `set -e` 또는 `|| { echo ...; exit 1; }` 명시
   - exit ≠ 0 시 `.merge-done`/`.done` 생성 차단
2. 회귀 테스트:
   - `tests/regression/test_finish_task_fail_closed.py` 신설
   - 시나리오: worktree finish 실패 모킹 → `.done` 미생성 검증
   - task-2364 시나리오 재현 (`.done` 17:08 → 머지 18:11) → 새 동작에서는 머지 실패 시 `.done` 미생성

#### allowed_resources
```yaml
allowed_resources:
  paths:
    - "scripts/finish-task.sh"
    - "tests/regression/test_finish_task_fail_closed.py"
  forbidden_paths:
    - "memory/**"
    - "dispatch.py"
    - "scripts/auto_merge.py"
    - "scripts/worktree_manager.py"  # 종료 코드만 신뢰, 동작 변경 X
  commands:
    - "git log"
    - "git diff"
    - "pytest tests/regression/test_finish_task_fail_closed.py"
  merge_policy: "tiered"
  ttl_hours: 8
```

#### 검증 기준
- `pytest tests/regression/test_finish_task_fail_closed.py` PASS
- 기존 `tests/dev7/test_scope_guard.py` 회귀 PASS (12 케이스)
- `scripts/finish-task.sh` 실행 시 worktree finish 실패 → exit code 1 + `.failed` 이벤트 + `.done` 미생성

---

### 후속 task 2 — P1 옵션 D 구현 (task-2369 머지 후 dispatch)

**가칭**: task-2370-done-semantics-option-d
**팀**: 1팀+7팀 협업 (auto_merge.py = 7팀, finish-task.sh = 7팀, dashboard = 1팀)
**레벨**: Lv.4 (시스템-wide 변경)
**우선순위**: P1
**의존**: task-2369 머지 완료

#### 작업 범위 (Phase 분할)

**Phase A — 마커 모델 + state.json SoT**
- `memory/state/{task_id}.json` 스키마 신설
- 상태 enum: `WORK_PUSHED | PR_OPEN | PR_MERGING | PR_MERGED | LOCAL_MERGED | SYSTEM_DONE | MERGE_FAILED`
- `.work-done` JSON 스키마: `{task_id, kind, project_path?, pr_url?}`
- `.merged` JSON 스키마: `{task_id, merge_commit_sha, mergedAt, kind}`
- `.merge-failed` JSON 스키마: `{task_id, retry_count, last_error}`

**Phase B — task.yaml schema 확장**
- `kind: code | meta` 필드 신설 (기본값 `code`)
- `merge_required: bool` 필드 신설 (기본값 `kind=code`면 true)
- schema validator: 미설정 + project_path 부재 시 CI fail
- 본 task-2368 자체에 `kind: meta` 적용 (자기참조 검증)

**Phase C — `scripts/finish-task.sh` 마커 변경**
- 기존 `.done` 생성 → `.work-done` 생성으로 전환
- 시스템·문서 task (`kind: meta`) → `.work-done` + `.merged` 동시 생성 분기
- `.done` symlink 6개월 호환 shim 유지

**Phase D — `scripts/auto_merge.py` reconciler 패턴 전환**
- `MarkerScanner.scan_work_done()` 신설
- `Reconciler.tick()` 분리 (15s 주기, 폴링)
- `gh pr view --json mergedAt` 검증 후 atomic `.merged` 생성 (`flock` + `os.rename`)
- 5회 retry 초과 시 `.merge-failed` + 알림

**Phase E — 마이그레이션 (4 소비자, P0/P1/P2 우선순위)**
- P0: `notify-completion.py` (작업 완료 / 머지 완료 메시지 분리), `session-watchdog.sh` (`.merged` 시 종료)
- P1: `auto_merge.py` (Phase D에서 동시 처리)
- P2: `whisper-compile.py` (`.work-done` 트리거 조기 컴파일)

**Phase F — Dashboard UI (1팀 이리스)**
- `dashboard/components/TaskStatusBadge.tsx` 3-state enum 확장
- `dashboard/api/task_state.py` `pending_merge` 큐 응답
- "오늘의 완료" 카운터 2분할 카드 (작업 완료 N건 / 머지 완료 M건)

**Phase G — 알림 UX (Tier 결합 + dwell 90초)**
- `notify-completion.py` Tier별 알림 분기
- dwell 90초 윈도우 구현 (위치 결정 필요 — Phase G 시작 시)
- `.merge-failed` 즉시 알림 분기

**Phase H — 12-cell 호환성 회귀 테스트 (아르고스)**
- `tests/regression/test_done_marker_consumers.py` (12 cell 매트릭스)
- `tests/regression/test_meta_task_terminal_state.py` (시스템 task)
- `tests/regression/test_merge_failure_escalation.py` (5회 retry → `.merge-failed`)

#### allowed_resources
```yaml
allowed_resources:
  paths:
    - "scripts/finish-task.sh"
    - "scripts/auto_merge.py"
    - "scripts/notify-completion.py"
    - "scripts/session-watchdog.sh"
    - "scripts/whisper-compile.py"
    - "memory/state/**"
    - "dispatch.py"            # task.yaml schema 검증
    - "dashboard/components/TaskStatusBadge.tsx"
    - "dashboard/api/task_state.py"
    - "tests/regression/test_done_marker_*.py"
    - "tests/regression/test_meta_task_*.py"
    - "tests/regression/test_merge_failure_*.py"
    - "docs/task-lifecycle.md"  # 신규 문서
  forbidden_paths:
    - "memory/capabilities/**"  # P0 결정 보존
    - "memory/specs/bot-capability-model.md"
    - "memory/audit/**"
    - "CLAUDE.md"
  commands:
    - "git log"
    - "git diff"
    - "gh pr view"
    - "gh pr list"
    - "pytest tests/regression/"
  merge_policy: "tiered"
  ttl_hours: 48
```

#### 검증 기준
- 12-cell 호환성 매트릭스 PASS
- task-2364 회귀 시나리오 재현 → 잘못 보고 0건
- 시스템·문서 task (본 task-2368 자체) `kind: meta` 처리 → terminal state 인정
- 5회 retry 초과 → `.merge-failed` + 알림 검증
- 1주일 shadow mode 운영 (기존 마커와 새 판정 diff 로깅)

---

### 후속 task 3 — P2 안정화 + Merkle 서명 (task-2370 안정화 후)

**가칭**: task-2371-done-semantics-stabilization
**팀**: 7팀 (보안 강화)
**레벨**: Lv.3
**우선순위**: P2
**의존**: task-2370 머지 + 1주일 shadow mode 통과

#### 작업 범위
1. **임시 운영 가드 제거** — 아누 보고 함수의 `gh pr view --json mergedAt` 검증 코드 제거 (옵션 D가 안정 작동 시 불필요)
2. **Merkle-style HMAC 서명** (마아트 보류 안건) 도입 검토:
   - `.merged` 마커 내부에 HMAC 서명 추가
   - `verify-done.sh` 검증 스크립트 신설
   - 키 관리 + 시계 동기화 비용 평가 후 채택/기각 결정
3. **롤백 플래그 제거** — `LEGACY_DONE_SEMANTICS=1` 환경변수 1개월 후 제거

---

## 임시 운영 가드 (옵션 D 구현 전 즉시 적용)

> 회장 승인 + task-2369 dispatch 전에 즉시 적용 가능. 선택적.

### 아누 보고 함수에 mergedAt 검증 강제

**위치**: 아누 알림 발송 함수 (위치 미정 — 회장 결정)

**의사 코드**:
```python
def report_to_chairman(task_id, message):
    pr_data = subprocess.run(
        ["gh", "pr", view, "--json", "mergedAt", ...],
        ...
    )
    merged_at = json.loads(pr_data.stdout).get("mergedAt")
    done_mtime = os.path.getmtime(f"memory/events/{task_id}.done")

    if merged_at is None or (time.time() - done_mtime > 600):
        message = message.replace("머지 완료", "머지 진행 중")

    send_telegram(message)
```

**효과**: silent corruption 즉시 차단 (task-2364 케이스 재현 시 잘못 보고 0건)
**리스크**: 운영 룰 의존, 시스템 가드 부재 (옵션 D가 정식 해결책)

---

## 회장 승인 사항

- [ ] 옵션 D 채택 승인
- [ ] task-2369 (P0 핫픽스) 즉시 dispatch 승인
- [ ] task-2370 (P1 옵션 D 구현) 범위 + 팀 배정 승인 (1팀+7팀 협업)
- [ ] task-2367 (dev7 P1 Tiered Auto-Merge) 처리 결정:
  - (A) 일시 보류 → task-2370 후 범위 조정 / (B) task-2370과 병행 / (C) task-2370에 흡수
- [ ] 임시 운영 가드 (아누 mergedAt 검증) 즉시 적용 여부

## 비고

- 본 초안은 **DRAFT** 상태입니다. 회장 승인 + 아누 정식 dispatch 전 구현 진행 금지.
- 각 후속 task의 정확한 task_id는 dispatch 시점에 부여됩니다 (현재는 가칭).
- 미팅 합의 사항 변경/추가 시 본 초안 재작성 필요.
