# task-448.1 완료 보고서: 자기체이닝 인프라 긴급 수정 (6개 항목)

## 작업 요약
에이전트 미팅에서 확인된 자기체이닝 인프라 6개 구조적 결함을 수정.

## 수정 항목

### 1. [CRITICAL] notify-completion.py — dispatch 실제 구현 ✅
- `dispatch_next_phase()` 반환값이 `action=dispatch`일 때 dispatch.py를 subprocess로 실제 호출
- dispatch 실패 시 `.done.clear` 파일 삭제하여 재시도 허용
- dispatch 타임아웃 시에도 동일하게 `.done.clear` 삭제

### 2. [CRITICAL] chain.py — ANU_KEY 하드코딩 제거 ✅
- 35행: 기본값 `"c119085addb0f8b7"` → `""` 변경
- `_cron_notify()` 시작부에 ANU_KEY 미설정 시 graceful skip 추가

### 3. [CRITICAL] chain.py — bash -c 쉘 인젝션 수정 ✅
- `import re`, `import shlex` 추가
- `_SAFE_ID_RE` 정규식 + `_validate_safe_id()` 화이트리스트 검증 함수 추가
- `_dispatch_phase()` 내부를 f-string bash -c → subprocess 리스트 방식으로 전환
- `.env.keys`는 `shlex.quote()`로 안전하게 source 후 env dict에 로드
- chain_id, team, level 값에 대한 영숫자+하이픈+밑줄+점만 허용

### 4. [HIGH] team_prompts.py — 모듈레벨 크래시 제거 ✅
- 18-22행 모듈 레벨 `raise EnvironmentError` 삭제
- `_get_anu_key()` 함수 추가 (사용 시점 fail-fast 패턴)
- `_build_direct_prompt()`, `_build_glm_prompt()` 내부에서 `{ANU_KEY}` → `{_get_anu_key()}` 변경
- 기존 테스트가 ANU_KEY 없이도 import 가능하도록 `tests/conftest.py` autouse fixture 추가

### 5. [HIGH] DIRECT-WORKFLOW.md Step 9 조건 분기 ✅
- chain.py 체인(dispatch.py --chain)과 chain_manager.py 체인을 구분하는 조건 추가
- chain.py 체인일 때만 `chain.py task-done` 실행, 그 외는 Step 9 스킵

### 6. [MEDIUM] insuwiki-p2p3.lock 방치 파일 정리 ✅
- `/home/jay/workspace/memory/chains/insuwiki-p2p3.lock` 삭제 완료

## 생성/수정 파일 목록

**수정된 파일:**
- `/home/jay/workspace/scripts/notify-completion.py` — dispatch 실제 호출 구현
- `/home/jay/workspace/chain.py` — ANU_KEY 기본값 제거 + _cron_notify graceful skip + 쉘 인젝션 방어
- `/home/jay/workspace/prompts/team_prompts.py` — 모듈레벨 crash 제거, _get_anu_key() 패턴
- `/home/jay/workspace/prompts/DIRECT-WORKFLOW.md` — Step 9 조건 분기
- `/home/jay/workspace/tests/test_notify_completion.py` — TestDispatchExecution 클래스 추가 (2개 테스트)
- `/home/jay/workspace/tests/test_chain.py` — TestCronNotifyGracefulSkip, TestShellInjectionDefense 추가 (5개 테스트) + task-file 플래그 테스트 수정
- `/home/jay/workspace/tests/test_team_prompts.py` — TestModuleLevelImportSafety 추가 (1개 테스트)

**생성된 파일:**
- `/home/jay/workspace/tests/conftest.py` — 전역 ANU_KEY fixture

**삭제된 파일:**
- `/home/jay/workspace/memory/chains/insuwiki-p2p3.lock` — stale lock 파일

## 테스트 결과
- pytest 전체: **810 passed, 0 failed**
- pyright: **0 errors, 0 warnings**
- black + isort: **OK**

### 추가된 통합 테스트 (8개)
1. `test_mid_chain_dispatch_calls_subprocess` — dispatch.py 실제 호출 확인
2. `test_dispatch_failure_removes_done_clear` — dispatch 실패 시 .done.clear 삭제 확인
3. `test_import_without_anu_key_no_crash` — ANU_KEY 없이 team_prompts import 성공 확인
4. `test_cron_notify_skips_when_no_anu_key` — ANU_KEY 없으면 graceful skip
5. `test_cron_notify_works_when_anu_key_set` — ANU_KEY 있으면 정상 호출
6. `test_dispatch_phase_rejects_injection_in_chain_id` — chain_id 인젝션 차단
7. `test_dispatch_phase_rejects_injection_in_team` — team 인젝션 차단
8. `test_dispatch_phase_accepts_valid_ids` — 정상 ID 통과 확인

## QC 자동 검증 결과
- test_runner: PASS (810 passed)
- pyright_check: PASS (0 errors)
- style_check: PASS (black + isort OK)
- data_integrity: PASS

## 비고
- chain.py의 `utils.logger` import는 pyright에서 `reportMissingImports`로 표시되지만, 런타임 `sys.path.insert(0, ...)` 동적 경로 추가로 정상 동작하는 기존 사전 존재 문제임
- 기존 test_dispatch.py, test_integration.py, test_regression.py도 `_get_anu_key()` 변경의 영향을 받아 conftest.py로 전역 해결
