# TASK2749 — COKACDIR CRON DAEMON FIRE BLOCKER DIAGNOSIS (read-only)

상태: `TASK2749_COKACDIR_CRON_DAEMON_FIRE_BLOCKER_DIAG_REQUIRED_ACTIVE_FALSE`
수행: 2026-06-15 KST / ANU / read-only (코드/systemd/recanary/flag/cron/live fire 0 · ACTIVE=false)

## ROOT CAUSE (confidence: 高 — cron.log 명시적 증거)
**same-chat busy skip.** callback wake cron(C7B5018F)은 ANU와 **같은 chat 6937032012**를 대상으로 등록됐는데, 그 chat이 **ANU 활성 대화 세션(이 세션)으로 busy**라서 cokacdir cron daemon이 발사를 **의도적으로 skip**했다.

cron.log 증거 (`~/.cokacdir/debug/cron.log`):
```
[read_schedule_entry] result: id=C7B5018F, type=absolute, schedule=2026-06-14 23:52:32, last_run=None
[scheduler_loop] id=C7B5018F, is_already_pending=true
[scheduler_loop] id=C7B5018F, should execute, is_busy=true
[scheduler_loop] id=C7B5018F, chat busy, already pending → skip
```
→ daemon은 (1) C7B5018F를 정상 read, (2) `should execute`(발사시각 23:52:32 지남) 판정, (3) 단 `chat busy`(chat 6937032012가 ANU 대화로 점유) + `already pending`(이미 큐) → **skip**.

## 완료 보고 (회장 항목)
1. **C7B5018F 등록 proof**: cron.log `read_schedule_entry result: id=C7B5018F, type=absolute, schedule=2026-06-14 23:52:32` (schedule/C7B5018F.json 정상 생성, cron-remove로 삭제됨 `delete_schedule_entry removed=true`)
2. **due/fire_at 분석**: type=absolute, schedule="2026-06-14 23:52:32"(KST), last_run=None → due 정상(현재>발사시각). timestamp 형식 정상.
3. **daemon 상태**: `cokacdir --ccserver`(PID 2446012, Jun08~ alive, 247분 CPU) **정상 작동**. scheduler_loop이 C7B5018F를 polling함.
4. **daemon log 분석**: should execute 판정 후 `chat busy, already pending → skip`. fire 시도 자체를 chat busy로 중단.
5. **schedule_history 미기록 원인**: 발사(execute)가 skip돼서 실행 기록 0 → schedule_history/cron-history 0. (skip은 실행이 아니므로 미기록)
6. **cron-history 미기록 원인**: 동일 — fire 안 됨(skip) → history 0.
7. **key/user/store mismatch**: 없음. ANU key 등록·daemon이 같은 store(`~/.cokacdir/schedule/`) polling·user jay 일치.
8. **timezone mismatch**: 없음. 서버/cokacdir 모두 KST(+0900). schedule 23:52:32 KST, 현재>발사시각 정상.
9. **v1 late/misfire 공통점**: v1 real-fire도 same-chat busy로 ANU 세션 active 중 skip → ANU 세션 **종료(idle) 후 late fire**됐음. v5는 ANU(이 세션)가 계속 active라 영구 skip → 내가 제거. **동일 root cause(same-chat busy skip)**.

## 원인 분류: cokacdir cron 설계 + 운영 절차 (코드/systemd 아님)
- **코드(.py/.sh) 문제 아님**: owner-pickup runner/driver는 정상(WAKE_BUILT·LAUNCHED·cron 등록 성공).
- **systemd 문제 아님**: anu-pickup.path/service 정상.
- **cokacdir cron daemon 설계**: daemon은 **같은 chat에 active 세션이 있으면 새 spawn cron을 skip**(동시 2 세션 방지 = 의도된 정책). callback wake cron이 ANU와 같은 chat을 대상으로 하므로, ANU active 중엔 발사 안 됨.
- **운영/검증 절차 문제**: callback wake 발사 검증을 **ANU active 세션(이 대화) 중에 시도**해서 구조적으로 skip됨.

## ★ 핵심 통찰 — normal callback의 실제 동작
normal callback 목적 = "dev 봇 끝 → ANU idle이면 자동으로 ANU 깨우기". 
- **ANU idle**: callback cron 발사 → ANU spawn → 자동 수거 (정상 동작, 검증 필요)
- **ANU active(대화 중)**: daemon skip(이미 깨어있으니 불필요) → ANU 직접 처리
→ **same-chat busy skip은 bug가 아니라 feature 가능성**(ANU 중복 spawn 방지). 단 검증은 ANU idle window에서만 가능.

## file-level fix / guard / wiring 후보
- **코드 fix 불요**(daemon/runner 정상). 단 **검증 절차를 파일에 결선** 필요:
  - **execution packet v2 / master runbook**: "WAKE_BUILT recanary의 cron 발사 검증은 **ANU idle window 필요**(active 중 same-chat busy skip). cron 등록(LAUNCHED) 후 ANU 세션 종료→idle→daemon fire→ANU spawn 관측" 절차 추가.
  - **executable guard/test**: callback cron 등록 후 `cron.log`에서 `chat busy → skip` vs `executing` 판별하는 checker(read-only). schedule_history/cron-history/workspace 중 1개 fire proof 확인 guard.
  - **preflight checker**: recanary 전 "현재 chat에 active ANU 세션 있으면 callback fire 검증 불가" 경고.
- **대안 D안(direct spawn)**: owner-pickup runner가 cron daemon 의존 없이 spawn. 단 same-chat busy 동일 문제(ANU active 중 2 세션) → daemon skip 정책과 충돌. 큰 설계 변경, 별도 논의.

## 회장 승인 없이 가능한 read-only 검증
- cron.log skip 사유 확인(완료). 다른 chat으로 callback cron 발사 시 fire되는지(별도 chat 필요·승인).

## 회장 승인 필요한 write/change
- packet/runbook에 idle-window 검증 절차 결선.
- checker/guard 스크립트 구현(별도 task).
- ANU idle window controlled test(callback cron 발사→ANU spawn 관측).

## 다음 task로 발행 가능한 구현 범위
1. **TASK2750(가칭)**: packet/runbook에 "WAKE_BUILT cron 발사 검증=ANU idle window" 절차 + cron.log skip checker(read-only guard) + schedule_history/cron-history fire proof 확인 결선.
2. controlled idle-window test: ANU 세션 종료 후 callback cron 발사 관측(또는 별도 chat 대상).

## normal callback 자동화까지 남은 gap
- 코드 경로: **완성**(WAKE_BUILT→owner-proof→cron 등록 LAUNCHED→collector_result).
- 미검증: ANU idle 시 daemon이 callback cron을 실제 fire→ANU spawn. **이건 설계상 작동 예상**(v1서 idle 후 late fire 실증). same-chat busy(ANU active)에서만 skip.
- 즉 자동화는 거의 완성. **남은 건 "ANU idle window에서 fire→spawn 실증" 1건**(controlled test) + 검증 절차 파일 결선.

★ read-only 진단. 코드/systemd/recanary/flag/cron 미실행. ACTIVE=false 유지.
