# task-1275.1 완료 보고서: dispatch.py task-counter 정합성 보장 개선

## SCQA

**S**: dispatch.py의 `generate_task_id()`가 `.task-counter` 파일 기반으로 자동 ID를 생성하며, 현재 카운터 값은 1275이다.

**C**: `--task-id`로 직접 지정(예: task-1274.1) 시 카운터 파일이 업데이트되지 않아, 이후 자동 생성 시 1253부터 재시작 → 기존 task ID와 충돌, 보고서/타이머 덮어쓰기 발생.

**Q**: 외부 지정 task_id와 자동 생성 ID 간 충돌을 방지할 수 있는가?

**A**: 3가지 Fix 적용으로 해결. (1) `generate_task_id()`에 카운터 파일에서 읽은 경우에만 timers.json 최대값과 비교 보정, (2) `_sync_counter_if_needed()` 함수 신규 생성 — 외부 task_id가 카운터보다 크면 `given_num + 1`로 업데이트, (3) `dispatch_task()`와 `_dispatch_composite()` 모두에 else 분기로 동기화 호출. 기존 테스트 141건 + 신규 테스트 5건 = 총 146건 전체 통과.

## 수정 내용

### Fix 1: generate_task_id() 정합성 체크 (dispatch.py:367-372)
- `from_counter` 플래그 도입: 카운터 파일에서 정상적으로 읽은 경우만 True
- `from_counter`가 True일 때만 `_compute_next_id_from_timers(timer_file)` 호출하여 비교
- 카운터 < timers 최대이면 WARNING 로그 후 timers 최대로 보정
- 카운터 파일이 없거나 손상된 경우 이미 `_compute_next_id_from_timers()`에서 정확한 값을 받으므로 이중 호출 방지

### Fix 2: _sync_counter_if_needed() 신규 함수 (dispatch.py:405-430)
- 외부 지정 task_id에서 숫자 파싱 → 현재 카운터와 비교
- `given_num >= current`이면 `given_num + 1`로 카운터 업데이트
- `fcntl.LOCK_EX` 파일 락 사용, try-finally로 안전 해제

### Fix 3: dispatch_task() / _dispatch_composite() else 분기 추가
- `dispatch_task()` (dispatch.py:902-906): task_id 외부 지정 시 `_sync_counter_if_needed()` 호출
- `_dispatch_composite()` (dispatch.py:656-660): 동일 패턴 적용

## 산출물

- `/home/jay/workspace/dispatch.py` (수정)
- `/home/jay/workspace/teams/dev1/tests/test_dispatch_counter_sync.py` (신규)

## 테스트 결과

기존 테스트 141건 통과 (0.75s) + 신규 테스트 5건 통과 (0.07s):

- `test_generate_task_id_counter_less_than_timers` — 카운터(100) < timers(200) → task-201.1 생성, 카운터=202 보정
- `test_generate_task_id_counter_greater_than_timers` — 카운터(300) > timers(200) → task-300.1 생성, 카운터=301 유지
- `test_sync_counter_if_needed_external_larger` — task-1280.1 지정, 카운터(100→1281)
- `test_sync_counter_if_needed_external_smaller` — task-1200.1 지정, 카운터(1300) 변경 없음
- `test_sync_counter_if_needed_invalid_format` — "invalid-id" → 예외 없이 무시, 카운터(500) 변경 없음

## 발견 이슈 및 해결

### 자체 해결 (4건)
1. **Fix 1의 _compute_next_id_from_timers 이중 호출로 기존 테스트 회귀** — `from_counter` 플래그를 도입하여 카운터 파일에서 읽은 경우에만 timers 비교 수행. 카운터 파일 없는 경로에서는 이미 timers 기반 값을 사용하므로 재비교 불필요 (dispatch.py:353,367)
2. **테스트 파일 미사용 import (MagicMock, pytest)** — 제거하여 정리 (test_dispatch_counter_sync.py:15,17)
3. **테스트 미사용 변수 lock_path** — 해당 변수 선언 제거 (test_dispatch_counter_sync.py:94)
4. **style_check WARN (black/isort)** — `black` + `isort` 적용으로 해결

### 범위 외 미해결 (0건)
없음.
