# task-687.1 완료 보고: dispatch.py .env.keys 자동 로드 개선

## SCQA

**S**: dispatch.py와 chain.py는 실행 시 `COKACDIR_KEY_ANU` 등 환경변수에 의존하나, cokacdir 스케줄러를 통해 실행되는 세션에서는 `.env.keys`가 source되지 않아 `OSError`로 실패한다.

**C**: 매번 `source .env.keys && python3 dispatch.py ...` 수동 실행이 필요하여 휴먼에러가 반복적으로 발생한다.

**Q**: `.env.keys`를 프로그래밍적으로 자동 로드하여 환경변수 누락을 방지할 수 있는가?

**A**: `utils/env_loader.py`에 `load_env_keys()` 유틸리티를 구현하고, dispatch.py와 chain.py의 `main()` 최상단에서 호출하도록 수정하여 해결. pytest 5건 전체 통과, pyright 에러 0건.

## 작업 내역

### 1. 신규 파일: `utils/env_loader.py`
- `load_env_keys(path)` 함수 구현
- `export KEY=VALUE` 형식 파싱 (export 접두어 제거 → `=` 기준 분리)
- `os.environ.setdefault()` 사용으로 기존 환경변수 보존
- 주석(`#`), 빈 줄 무시
- 따옴표(`"`, `'`) 감싸진 값 자동 제거
- 파일 미존재 시 경고 로그만 출력, 크래시 없음

### 2. 수정 파일: `dispatch.py` (line 571-575)
- `main()` 최상단에 `load_env_keys()` 호출 추가

### 3. 수정 파일: `chain.py` (line 497-501)
- `main()` 최상단에 `load_env_keys()` 호출 추가

### 4. 신규 파일: `tests/test_env_loader.py`
- 5개 테스트 케이스 작성 (정상로드, 파일없음, 덮어쓰기방지, 따옴표처리, 주석/빈줄)

## 생성/수정 파일 목록

- `/home/jay/workspace/utils/env_loader.py` (신규)
- `/home/jay/workspace/dispatch.py` (수정: main() 상단 4줄 추가)
- `/home/jay/workspace/chain.py` (수정: main() 상단 4줄 추가)
- `/home/jay/workspace/tests/test_env_loader.py` (신규)

## 테스트 결과

```
tests/test_env_loader.py::TestLoadEnvKeysNormalLoad::test_loads_variables_and_returns_count PASSED
tests/test_env_loader.py::TestLoadEnvKeysMissingFile::test_missing_file_returns_zero_without_exception PASSED
tests/test_env_loader.py::TestLoadEnvKeysNoOverwrite::test_existing_env_var_not_overwritten PASSED
tests/test_env_loader.py::TestLoadEnvKeysQuotedValues::test_double_quoted_value_stripped PASSED
tests/test_env_loader.py::TestLoadEnvKeysCommentsAndBlankLines::test_comments_and_blank_lines_ignored PASSED

5 passed in 0.06s
```

- pyright: 0 errors, 0 warnings, 0 informations
- black/isort: 포매팅 적용 완료

## 발견 이슈 및 해결

### 자체 해결 (3건)
1. **chain.py에 ENV_KEYS 변수는 있으나 자체 environ에는 미적용** — `_dispatch_phase()`에서 subprocess 환경에만 로드하고 자체 `os.environ`에는 적용하지 않아 `ANU_KEY = os.environ.get("COKACDIR_KEY_ANU", "")` 등이 빈 문자열로 남는 문제. → `main()` 상단에 `load_env_keys()` 추가로 해결
2. **env_loader에 OSError 방어 누락 가능성** — 파일 존재하나 권한 없는 경우 대비. → `try/except OSError` 추가하여 경고 로그 후 0 반환
3. **테스트 간 환경변수 오염** — `monkeypatch.delenv()/setenv()` 적용으로 테스트 격리 보장

## 기존 테스트 실패 (본 작업 범위 외)

⚠️ 기존 테스트 실패 1건 (본 작업 범위 외): `tests/test_chain_manager.py::TestNext::test_next_creates_missing_task_file_from_original`
- 원인: chain_manager.py의 next 명령이 지시서 파일 자동 생성을 하지 않는 기존 이슈
- 본 작업(env_loader)과 무관

## QC 자동 검증 결과

- **overall**: PASS (6 PASS, 4 SKIP)
- file_check: PASS (4/4 파일 확인)
- data_integrity: PASS
- tdd_check: PASS (테스트+구현 파일 모두 존재)
- pyright_check: PASS (0 errors, 0 warnings)
- style_check: PASS (black: OK, isort: OK)
- test_runner: SKIP (--test-dir 미지정, 수동 테스트 5/5 통과 확인)
- 비고: `tests/test_chain_manager.py::TestNext::test_next_creates_missing_task_file_from_original` 기존 실패 1건 (본 작업 무관)
