# task-486.1 보고서: 고스트 태스크 추가 수정 — 3팀(Sonnet) 분석 기반

**작성자**: 헤르메스 (Hermes) / dev1-team
**작성일**: 2026-03-12
**상태**: 완료

---

## 작업 요약

2팀(Opus) 분석으로 6건 수정 완료(task-485.1) 후, 3팀(Sonnet) 분석(task-482.1)에서 추가 발견된 2건을 반영.

---

## 수정 A [HIGH]: test_dispatch.py 테스트 격리 — subprocess.run 모킹 추가

**파일**: `/home/jay/workspace/tests/test_dispatch.py`

4개 테스트가 `subprocess.run`을 모킹하지 않아 실제 `task-timer.py`가 실행되어 프로덕션 `task-timers.json`에 ghost task(task-1.1, task-4.1)가 기록되던 문제.

수정된 테스트:
1. `test_dispatch_nonexistent_project` — subprocess mock 추가
2. `test_dispatch_no_bot_key` — subprocess mock 추가
3. `test_dispatch_bot_key_none_exits` — subprocess mock 추가
4. `test_marketing_all_bots_busy_returns_error` — subprocess mock 추가

각 테스트에 동일 패턴 적용:
```python
with (
    patch.object(dispatch_mod, "subprocess") as mock_sub,
    patch.object(dispatch_mod, "BOT_KEYS", {...}),
):
    mock_sub.run.return_value = MagicMock(returncode=0, stdout="{}", stderr="")
    result = dispatch_mod.dispatch(...)
```

---

## 수정 B [MEDIUM]: task-timer.py start_task() — stale 상태 보호 추가

**파일**: `/home/jay/workspace/memory/task-timer.py`

`start_task()`에서 completed만 거부하고 stale은 통과 → running으로 재전환되는 문제.
completed 가드 바로 아래에 stale 가드 추가:

```python
# stale task 재시작 방지 (task-486.1)
if existing and existing.get("status") == "stale":
    logger.warning(f"stale task 재시작 시도 거부: {task_id}")
    return {"status": "error", "reason": f"task_id '{task_id}' is in stale state. Use a new ID."}
```

---

## 생성/수정 파일 목록

- `/home/jay/workspace/tests/test_dispatch.py` — 수정 (4개 테스트에 subprocess mock 추가)
- `/home/jay/workspace/memory/task-timer.py` — 수정 (stale 가드 추가)
- `/home/jay/workspace/tests/test_task_timer.py` — 수정 (TestStaleGuard 테스트 2건 추가)

---

## 테스트 결과

- `tests/test_dispatch.py`: 82 passed
- `tests/test_task_timer.py`: 126 passed (기존 124 + 신규 2)
- **전체 합산: 208 passed, 0 failed**
- 프로덕션 `task-timers.json`: task-1.1, task-4.1 모두 "completed" 상태 유지 (오염 없음)
- pyright: 기존 import 관련 경고만 존재, 신규 타입 에러 없음

---

## 셀프 QC 체크리스트

- [x] 1. 이 변경이 다른 파일에 영향을 미치는가? → test_dispatch.py, task-timer.py, test_task_timer.py만 변경. dashboard/ 미접촉.
- [x] 2. 이 로직의 엣지 케이스는 무엇인가? → stale 상태 재시작, completed 상태 재시작 모두 거부 확인. running/reserved는 기존 로직 유지.
- [x] 3. 이 구현이 작업 지시와 정확히 일치하는가? → 수정 A(4개 테스트 mock), 수정 B(stale 가드) 모두 지시대로 구현.
- [x] 4. 에러 처리와 보안은 확인했는가? → stale 거부 시 명확한 에러 메시지 반환, 로깅 포함.
- [x] 5. 테스트가 모든 경로를 커버하는가? → stale 거부 + 데이터 보존 2개 테스트 추가.

---

## 비고

- 2팀(task-485.1) + 3팀(task-482.1) 분석을 통합한 최종 수정 완료
- task-485.1에서 수정한 코드는 변경 없이 유지
- 기존 ghost task(task-1.1, task-4.1)는 "completed" 상태 유지 → 삭제 불필요
