# task-3014 — /generate 카페 채널 추가 + AI 모델 선택(플랜 상한)

**레벨**: Lv.2 · **팀**: dev7-team (이참나) · **회장 승인 완료** (2026-08-25)

## 회장 요구 (원문)
> 1. 카페용 글 작성 기능 추가
> 2. 고급옵션에서 AI모델 선택 부분 — **Claude Haiku · Sonnet · Opus · GPT** 4가지 중 선택.
>    Opus·GPT 는 최고품질로 **Hidden/Max 플랜만**, **Pro/Basic 은 Sonnet 까지**, **무료는 Haiku 만**.
> 3. (카페는) **무료부터 열고, 대신 haiku 만 선택 가능**하게.

---

## ★ ANU 실측 — 뼈대는 이미 있다

```
src/config/planSkillMap.ts
  PRESETS[] (id/name/skills/minPlan) · canUseSkill(planName, skillId) · PLAN_NAME_MAP
src/components/GenerateSettingsPanel.tsx
  CONTENT_PRESETS · GroupedSelect (고급옵션 패널)
src/pages/Generate.tsx:397-398
  // 무료 플랜은 naver-blog만 사용 가능
  const isLocked = isFree && ch.value !== "naver-blog";
server/main.py:1387
  model_tier = PLAN_LEVEL_MODEL_TIER.get(sort_order, "haiku")   ← 플랜이 모델을 자동 결정
server/main.py:1129
  "claude", "-p", "--model", model, "--output-format", "text"   ← claude CLI 호출 실적
```
플랜 5종(hidden·max·pro·basic·free)과 게이팅 구조가 이미 있다.
★ 위는 ANU 가 grep 으로 확인한 것이다. **네가 다시 확인하라.** 다르면 ANU 에 보고하라.

---

## 고칠 것

### ① 카페 채널 추가 — **전 플랜 개방**
- 채널 목록에 카페를 추가한다(`naver-cafe` 등, 기존 명명 규칙을 따르라)
- ★ **무료 플랜도 카페를 쓸 수 있다.** 현재 `isFree && ch.value !== "naver-blog"` 로 잠그는
  로직이 있는데, **채널로 막지 말고 ②의 모델 상한으로 차등**한다(회장 결정)
- 카페 글의 성격은 블로그와 크게 다르지 않다. **프롬프트/톤을 새로 설계하지 마라.**
  기존 블로그 경로를 재사용하되 채널 구분만 전달한다. 별도 조정이 필요해 보이면 **보고**하라

### ② AI 모델 선택 UI + 플랜 상한 (핵심)
지금은 **플랜이 모델을 자동 결정**한다. 이걸 **"플랜은 상한만 정하고 사용자가 그 안에서 고른다"** 로 바꾼다.

```
Free          →  Haiku
Basic · Pro   →  Haiku · Sonnet
Max · Hidden  →  Haiku · Sonnet · Opus · GPT
```

- 고급옵션에 **모델 선택 UI** 를 넣는다. 선택 불가한 모델은 **잠금 표시 + 사유**를 보여준다
  (★ 숨기지 말고 **보이되 잠그는** 편이 상위 플랜 유도에 맞다. 기존 `isLocked` 패턴 참고)
- 상한 판정은 **서버에서도 강제**한다. 프론트만 막으면 우회된다
  (`PLAN_LEVEL_MODEL_TIER` 를 "자동 결정"에서 "상한 검증"으로 재해석)
- ★ **플랜 이름 표기 주의**: 코드에 `PLAN_NAME_MAP` 이 있다(한글 표기 ↔ 영문 키).
  한쪽만 고치면 판정이 어긋난다

### ③ GPT 경로 확인 — 먼저 조사하라
회장 확정: **GPT 는 아누 시스템 내 codex 를 경로로 쓴다.**
- codex CLI 로 **글 생성**이 실제로 되는지 확인하라. 실적 참고: `server/newsletter_cross_verify.py`
  (task-2904 에서 OpenAI API → codex CLI 로 교체한 사례)
- ★ **안 되면 만들지 말고 ANU 에 보고하라.** 별도 API 키·과금이 필요하면 그것도 보고 대상이다
- Claude(haiku/sonnet/opus)는 기존 CLI 경로를 쓴다. **Opus 호출이 실제로 되는지도 확인**하라

---

## ★ 금지
- **프롬프트/스킬 체계 재설계** — 기존 `PRESETS`·`skills` 구조를 갈아엎지 마라
- **무료 플랜을 유료 기능에 개방** — 상한을 느슨하게 만들지 마라
- **프론트에서만 게이팅** — 서버 강제가 없으면 미완이다
- `src/pages/PolicyAnalysis.tsx` · `server/policy_analyzer.py` — task-3010 진행 영역
- `server/scripts/**` — task-3013 진행 영역
- 조용한 실패 신설 (모델 호출 실패를 성공처럼 표시하지 마라)

## allowed_resources

```yaml
allowed_resources:
  paths:
    - "src/pages/Generate.tsx"
    - "src/components/GenerateSettingsPanel.tsx"
    - "src/config/planSkillMap.ts"
    - "src/components/__tests__/**"
    - "src/pages/__tests__/**"
    - "server/main.py"
    - "server/tests/**"
    - "tests/**"
    - "memory/reports/task-3014.md"
  forbidden_paths:
    - "src/pages/PolicyAnalysis.tsx"
    - "src/pages/NewDesignComparison.tsx"
    - "server/policy_analyzer.py"
    - "server/silson/**"
    - "server/scripts/**"
    - "extension/**"
    - ".github/**"
  commands:
    - "npm run build"
    - "npx vitest run"
    - "pytest"
    - "python3"
  merge_policy: "tiered"
  ttl_hours: 72
```

## 검증
1. **플랜별 선택 가능 모델 표** — 5개 플랜 × 4개 모델 매트릭스를 **실측 결과**로 제시
2. **서버 강제 실증** — 프론트를 우회해 상한 밖 모델을 요청했을 때 **서버가 거부**하는지 확인
3. **카페 채널 동작** — 무료 플랜으로 카페 글이 실제로 생성되는지(Haiku), 상위 플랜에서 모델 변경이 반영되는지
4. **모델별 실호출** — Haiku·Sonnet·Opus·GPT 각각 **실제로 호출되는지** 확인.
   안 되는 것이 있으면 **그 사실을 명확히 보고**하라(추정으로 "된다"고 쓰지 마라)
5. **기존 경로 무회귀** — 블로그 글 생성이 그대로 동작하는지
6. **봉인** — 상한이 느슨해지면 FAIL 하는 테스트. **변이로 실증**하라
   (예: Free 가 Opus 를 고를 수 있게 바꿨을 때 테스트가 실제로 깨지는지)
7. `npm run build` EXIT=0 · `npx vitest run` · `pytest` 회귀 유지(**base 재측정 기준선**)

## 운영 계약
- `origin/main`(=`997fa5d`) 기준 `git pull --ff-only` 후 시작
- ★ `gh` 호출 시 `GH_TOKEN="$BOT_GITHUB_TOKEN"` 주입 필수 (회장 개인 PAT 금지 — 감사기록 오염)
- 워크플로우 `/home/jay/workspace/prompts/DIRECT-WORKFLOW.md` · QC `/home/jay/workspace/teams/shared/QC-RULES.md`
- `WORKSPACE_ROOT=/home/jay/workspace` · `CHAT_ID=6937032012` · 수집자 key `ANU_KEY=c119085addb0f8b7`
- 완료 경로는 `finish-task.sh` 실행이 유일하다. 수동 `.done` 금지.
- **명세와 실측이 다르면 임의 판단하지 말고 ANU 에 보고하라.**

★ 백엔드는 2026-08-25 14:40 KST `997fa5d` 로 배포됐다. `server/main.py` 변경은 **머지 후 배포해야 반영**된다.

## 완료 조건
카페 채널 전 플랜 개방 · 모델 선택 UI + 잠금 표시 · **서버 상한 강제 실증** ·
플랜×모델 매트릭스 실측 · 모델별 실호출 결과(되는 것/안 되는 것 구분) · 변이로 봉인 실증 · 회귀 유지

## 보고
**★★★ PR 생성까지가 범위다. 머지는 ANU 가 한다. 절대 직접 머지하지 마라.**
★ CI 워처가 `MERGE_READY` 를 내더라도 **자동 머지하지 마라.** 2026-08-25 에 워처 경로
자동 머지가 4회 발생해 현재 통제를 복구하는 중이다(task-3012).
`memory/reports/task-3014.md` 작성 후 표준 완료 콜백 등록. 콜백 프롬프트 **UTF-8 3900 bytes 이하**.
★ 봉투 첫 줄에 **"모델 4종 각각 실호출 성공 여부"** 를 담아라.

## goal_assertions (auto-generated)
- `npm run build`
- `npx vitest run`
