# task-2559+1 context-notes

## 발견 경위
- 2026-05-12 PR #114 task-2559 MERGED (`ea242814`)
- 라이브 환경 확인: dev1 cron 봇 PID 2939430 cwd `/home/jay/.cokacdir/workspace/B6F6E56A/` 활성
- 그러나 `BotProcessCollector().collect()` → `active_lead_count: 0`
- 원인 추적: `_parse_schedule_log("B6F6E56A")` → `B6F6E56A.log` 부재 (없음) → None → 격리

## schedule_history log 의 라이프사이클
- cron 작업이 **완료** 시점에 cokacdir 가 한 줄을 JSONL 로 append
- 진행 중에는 `.log.lock` / `.log.redacted` 파일만 부수적으로 존재할 수 있고 본 `<id>.log` 는 부재
- 본 사실은 `/home/jay/.cokacdir/schedule_history/` 디렉터리 listing 으로 어셀션 가능 — 활성 cron workspace 의 id 가 schedule_history 에 *.log 로 안 보임

## chat 격리 doctrine 의 권위 위치
- log 존재 시: log 의 `chat_id` 값이 권위 (회장 chat=6937032012 만 인정)
- log 부재 시: log 가 권위를 행사할 수 없음 → 대안 권위 필요
  - dispatch.py 봇: worktree cwd 자체가 회장 chat 소유 증거 (회장 사용자 jay 가 worktree 생성)
  - cron 봇 (본 hotfix 의 대상): cwd 패턴 `/home/jay/.cokacdir/workspace/<id>/` + process owner == jay
    → 두 조건 모두 jay user 본인 프로세스만 가능 (다른 user 가 동일 cwd 가질 수 없음)

## fallback 발동 조건의 완전성
- cwd 정규식 매칭(_CRON_CWD_RE) 통과 == `/home/jay/.cokacdir/workspace/<6~16hex>/`
- username == "jay" 어셀션
- `_parse_schedule_log` None (파일 부재, OSError, JSON 파싱 실패)
- 위 3조건 충족 시에만 fallback (chat 격리 위반 사례 폐쇄)

## display_name 매핑의 한계
- 본 fallback 은 verifier / prompt 둘 다 없으므로 bot_key 매핑 불가
- `display_name="unknown_cron_bot"` 으로 일관 박제 — bots_by_display 그룹화 가능
- `active_lead_count` 가 정확히 +1 되는 것이 본 hotfix 의 핵심 목적 (라이브 회귀 해소)
- 향후 후속 task 에서 `cokacdir --cron-list` 또는 `bot_settings_sync.last_sessions` 기반 추론 가능 (본 hotfix 범위 외)

## task-2559 본문 보존
- task-2559 의 `bot_process_collector.py` 메인 흐름(`get_subagent_children`, `signal_from_collector`, `is_lead_alive`, `_lead_matches`, regex 정의) 변경 0
- 추가된 것은 `LeadBotProcess.chat_id_resolution_source` 필드 1개 (None 기본값으로 backward-compatible)
- `_classify_lead` 분기 추가는 기존 PASS 경로를 변경하지 않음 — fallback 은 None 반환되던 시점에만 발동
- `data_loader.py` / `routes_get.py` / `server.py` 는 `chat_id_resolution_source` 를 참조하지 않으므로 zero-cost

## 라이브 검증 (PR merge 후 어셀션)
- `python3 -c "from bot_process_collector import BotProcessCollector; print(BotProcessCollector().collect()['active_lead_count'])"`
- 진행 중인 cron 봇 (예: dev1 B6F6E56A) 이 1개 이상이면 출력 ≥ 1
- 각 lead 의 `chat_id_resolution_source` 가 `"in_progress_fallback"` (log 부재 시) 또는 `"schedule_log"` (log 존재 시)

## 위험 평가
- 회귀 위험: 매우 낮음 — 변경 범위는 collector 의 단일 분기 + 신규 audit 필드. data_loader / API 미참조.
- 보안 위험: 0 — username=="jay" 게이트로 다른 user fallback 차단. 기존 psutil username 필터 (`_default_psutil_processes`) 와 2중 방어.
- chat 격리 doctrine 위반 위험: 0 — log 존재 + 다른 chat_id 케이스는 별도 분기에서 격리 유지. fixture 회귀 테스트로 박제.
