# finish-task.sh / cokacdir CLI wrapper unfork 영향 분석 (read-only) — 260523

task-2640 Track D 산출물 (★ 회장 verbatim: 본 batch 코드 수정 0 · 분석 spec 만).

기반:
- task-2640 spec §5 (`system_self_collector_enforcement_wiring_spec_260523.md`)
- 회장 결정 (2026-05-23 PR #142 직후): finish-task.sh / cokacdir 본체 수정 금지.
  단, 후속 unfork 회장 결정을 위한 영향/위험/정책 분석 자료 정리는 허용.

본 spec 은 **분석 + 위험 정리** 목적이며 어떠한 코드/스크립트도 수정하지 않는다.
별도 unfork 회장 결정 후 신규 task 로 발행 가능.

---

## 1. 현황 (260523 base = origin/main 93598660)

### 1.1 `scripts/finish-task.sh`
- 봇이 작업 완료 시 호출하는 단일 entry point.
- 현재 동작: 보고서 박제 · task-timer end · capability snapshot 검사 등 수행.
- **callback 자동 발사 미지원** — 봇은 별도 `cokacdir --cron` 호출로 callback
  등록을 수행하거나, 누락 시 SENDFILE_ONLY / NOT_REGISTERED 변종이 발생.

### 1.2 `cokacdir` CLI 본체
- 회장 외부 서비스 (`/usr/local/bin/cokacdir`). dev bot 영역 외.
- `--cron` 호출 시 `--key` 인자를 그대로 사용 → executor self-key 로 등록되어도
  CLI 본체는 차단하지 않음. SELF_COLLECTOR 변종 발생의 구조적 진입점.

### 1.3 SELF_COLLECTOR 변종 3회 재발 원인 (task-2625/2634/2639)
- 텍스트 doctrine 만 prompt 에 삽입 → 봇 자의적 해석.
- runtime path 결선 부재 → 코드 단언이 dispatch 진입에 강제되지 않음.
- finish-task.sh / cokacdir 단계의 fail-closed 가드 부재.

---

## 2. unfork 후보 시나리오

### 2.1 finish-task.sh callback 자동 발사 도입
**가설**: finish-task.sh 가 환경변수 ANU_KEY 를 읽고 자동으로 callback cron 을
발사하면 봇 자의적 해석에 의존하지 않고 결선이 강제된다.

**구현 후보**:
- `scripts/finish-task.sh` 내부에서 `cokacdir --cron --key $ANU_KEY ...` 호출.
- envelope 5축 + canonical_root 빌더는 `utils/anu_callback_registrar.py` 위임.
- schedule_id 회수 → result.json 박제 → finalize.

**영향**:
- 긍정: SELF_COLLECTOR 변종 봉쇄 (finish-task.sh 단계 fail-closed).
- 부정: finish-task.sh 가 cokacdir 실호출 진입점이 되어 책임 비대화.
- 부정: dry-run / regression 분리 어려움 (실 cron 사이드이펙트 가능).

**위험**:
- 환경변수 ANU_KEY 누락 시 자동 발사 실패 → 정책 PASS 인데 callback 0 위험.
- finish-task.sh 가 봇 lifecycle 의 핵심 진입점이라 회귀 위험 큼.
- 회장 verbatim "scripts/finish-task.sh 수정 금지" 위반.

**완화 정책 후보**:
- `bot_settings_policy_loader` 에 `finish_task_auto_callback=false` 기본값 추가.
- finish-task.sh 가 정책 필드 검사 후 활성화.
- 봇 lifecycle finalize 진입점에서 별도 검증 layer 추가 (Track C 이미 도입).

### 2.2 cokacdir CLI wrapper 도입
**가설**: `utils/cokacdir_safe_wrapper.py` 가 cokacdir 호출 전 SELF_COLLECTOR /
SENDFILE_ONLY / NOT_REGISTERED 차단 가드를 적용 → CLI 본체 무수정 유지.

**구현 후보**:
- `cokacdir_safe_wrapper.run(argv, *, executor_key, anu_key, prompt) -> dict`
- 호출 전 `dispatch.spawn_callback_contract_validator.validate_spawn_callback_contract`
  를 호출하여 fail-closed 검증.
- 통과 시 `subprocess.run(["cokacdir", ...])` 호출, 실패 시 NO_OP 반환.

**영향**:
- 긍정: CLI 본체 무수정. wrapper 만 도입 → 회장 제약 정합.
- 긍정: 모든 cokacdir 호출 지점을 wrapper 로 통합 → 단일 결선 지점.
- 부정: 기존 호출 지점이 분산되어 마이그레이션 비용 큼 (dispatch/__init__.py
  외에도 다수 호출 지점 존재).

**위험**:
- wrapper 우회 호출 가능 (raw `subprocess.run(["cokacdir", ...])`) → audit 필요.
- wrapper 채택 강제 메커니즘 부재 시 점진 결선 불가능.

**완화 정책 후보**:
- pre-commit hook 으로 raw cokacdir 호출 차단.
- audit logger 에 wrapper 외 호출 시점 기록 → 후속 회수.

### 2.3 finish-task.sh 정책 필드 체크
**가설**: finish-task.sh 가 `bot_settings.json` 의 `require_anu_callback_on_finish`
필드를 검사하여 callback 미등록 시 fail-closed exit.

**구현 후보**:
- finish-task.sh 진입 직후 `python3 -m utils.bot_settings_policy_loader check`.
- 실패 시 exit code !=0 → 봇 lifecycle 차단.

**영향**:
- 긍정: 정책 적용이 단순 (callback 자동 발사 없이 검증만).
- 부정: 봇이 finalize 전에 callback 을 직접 등록해야 함 → 자의적 해석 잔존.

**위험**:
- 봇이 검증 통과를 위해 dummy schedule_id 를 박제하는 우회 가능.
- 정책 검증과 실제 등록 사이의 race condition.

**완화 정책 후보**:
- Track A 의 spawn_callback_contract_validator 와 결선 (이중 안전).
- schedule_id 의 실시간 cokacdir history 교차검증 (cron-direct verify).

---

## 3. 권장 후속 unfork 우선순위

회장 결정 대기 (priority 순):

1. **2.2 cokacdir CLI wrapper 도입** — 회장 제약 정합 + 점진 결선 가능.
   wrapper 외 호출 audit 만 추가하면 회귀 위험 낮음.
2. **2.3 finish-task.sh 정책 필드 체크** — Track C 와 결선 자연스러움.
   finish-task.sh 수정량 최소 (정책 검증 호출만).
3. **2.1 finish-task.sh callback 자동 발사** — 가장 강력하지만 회귀 위험 큼.
   1+2 도입 후 평가 권장.

---

## 4. 본 batch 가 채택한 정책 (Track A/B/C — 코드 결선)

- Track A: `dispatch.spawn_callback_contract_validator` 신규 + dispatch entrypoint
  결선 (dispatch/__init__.py import + core.py spawn-time gate + prompt.py guard).
- Track B: `prompts/team_prompts._build_self_collector_doctrine_block` 자동 주입.
- Track C: `utils.bot_settings_policy_loader` 신규 + `config/callback_policy.json`
  후보 위치.

Track D 본 spec 은 **read-only** — finish-task.sh / cokacdir 본체 수정 0.
후속 unfork 회장 결정 시 본 spec 의 분석을 기반 자료로 활용한다.

---

## 5. 안전 불변식 (회장 verbatim 유지)

- `scripts/finish-task.sh` 무수정 (본 spec 분석만)
- `cokacdir` CLI 본체 무수정
- `replacement_pr_runner.py` / `merge_ready_classifier` / `merge_ready_dryrun_executor` 무수정
- ANU key `c119085addb0f8b7` 단일 출처 유지 (변경 0)
- envelope UTF-8 ≤3900 bytes 유지
- live cokacdir CLI 실호출 0
- merge / push / PR / cron / admin override 호출 0
- PR #141 pilot 재시도와 혼합 0
- foreign dirty 정리 0

---

## 6. frozen anchor (Track D)

- ANCHOR-D1: "finish-task.sh / cokacdir 본체 무수정 · read-only 분석 spec 만"
- ANCHOR-D2: "후속 unfork 후보 3종 (2.1 자동 발사 · 2.2 CLI wrapper · 2.3 정책 체크)"
- ANCHOR-D3: "권장 우선순위: 2.2 → 2.3 → 2.1 (회장 결정 대기)"
- ANCHOR-D4: "본 batch 는 Track A/B/C 코드 결선으로 SELF_COLLECTOR 변종 1차 봉쇄"
- ANCHOR-D5: "후속 unfork 결정 시 본 spec 의 영향/위험/완화 정책 자료 활용"
