diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md new file mode 100644 index 0000000..6a87909 --- /dev/null +++ b/docs/HANDOFF.md @@ -0,0 +1,63 @@ +# Vignette 핸드오프 노트 + +> 2026-06-26 02:0x KST · 세션 b00bd7f3 → 다음 세션. **새 세션은 이 파일부터 읽고 이어받는다.** + +## 프로젝트 +한신대 SW중심대학 산학협력 — 생성형 AI 심리상담 시뮬레이션 훈련 플랫폼 **Vignette**. +- repo: `D:\workspace\vignette` · github.com/yunchan8804-blip/vignette (**master, f869d25**) +- 학습자가 가상 내담자(AI 페르소나)와 상담 연습 → 백그라운드 평가 AI가 기법 라벨링·피드백. 3역할(학습자/교수자/관리자). + +## 라이브 URL +- **프론트(공개)**: https://vignette.chanpaca.net (= vignette-b1q.pages.dev, Cloudflare Pages) +- **API(터널)**: https://api-vignette.chanpaca.net (cloudflared named tunnel → localhost:8000) +- 라이브 경로: 로그인(학습자) → 학습자홈 → **연습 시작** → 상담세션 → **회기 시작** → 입력창 말걸기 → 서연(P1) 실응답 + +## ⚠️ 상주 인프라 (윤찬 PC, 세션 넘겨도 살아있음 — 안 끄면) +| 프로세스 | 포트 | 재시작 | +|---|---|---| +| 엔진 게이트웨이 (claude -p 상주풀) | 9099 | `cd apps/api && C:/Users/encep/AppData/Local/Programs/Python/Python311/python.exe -m uvicorn engine_gateway.gateway:app --host 127.0.0.1 --port 9099` | +| API 서버 (FastAPI) | 8000 | 아래 env로 `python -m uvicorn app.main:app --host 127.0.0.1 --port 8000` (WorkingDir apps/api) | +| cloudflared (vignette tunnel ca8c5be0) | — | `cloudflared tunnel --config C:\Users\encep\.cloudflared\vignette-config.yml run` | + +API env(필수): `ENGINE_URL=http://127.0.0.1:9099` `ENGINE_MODE=claude_cli` `ENVIRONMENT=dev` `CORS_ORIGINS=["https://vignette.chanpaca.net","https://vignette-b1q.pages.dev","http://localhost:5173"]` +- health 확인: `curl https://api-vignette.chanpaca.net/health` → 200 / `curl -X POST .../sessions -d '{"persona_code":"P1","theory_mode":"humanistic"}'` → 201 + +## ✅ 완료 (대시보드 구현·인프라) +- 프론트 7화면(로그인/학습자홈/세션/리뷰/교수자/관리자/설정) 공개배포 + 라이트테마 +- 백엔드 풀 라이브: 게이트웨이(/v1/generate·/v1/stream 어댑터) + API(orchestrator: 가드레일→상태머신→페르소나→엔진→평가) + **DB 없이 degraded(store 인메모리 폴백)** +- named tunnel + CORS + puppeteer 실화면 검증(서연 실응답) +- 커스텀도메인 vignette.chanpaca.net **SSL active** +- DB 마이그레이션 35테이블+pgvector (검증 후 Docker 내림. 운영 DB는 NAS PostgreSQL 설계) +- 합성 골든셋 62발화(P4-P7 비위기, `data/golden/`+`data/personas/`) + 평가AI few-shot 연결(`evaluator.py` GOLDEN_DIR) + +## 🔴 다음 세션이 이어받을 작업 (윤찬 최신 지시 2건) +### 1. 학습자홈 목업 제거 (최우선) — `apps/web/src/pages/LearnerHome.tsx` +윤찬: "신규 사용자인데 **12회 연습/수련님/이미 있는 회기 목록**이 가짜로 차있으면 안 돼. 애당초 목업이 없어야." +- 빼야 할 mock: `MOCK_WEEK`(doneCount/reviewPending/weeklyGoal), `MOCK_SESSIONS`(회기 목록), `MOCK_GROWTH`(성장 추세), `MOCK_NEXT`(추천), 253줄 `"지금까지 12회 연습했어요"`, `MOCK_LEARNER_NAME_FALLBACK`("도윤"/"수련님") +- 목표: 신규 사용자 **빈 상태(empty state)** — 0회, 빈 회기, "아직 연습 기록이 없어요 → 첫 상담 연습을 시작해보세요" CTA 중심. 또는 API(`GET /sessions` 류)에서 실제 사용자 데이터 로드(없으면 빈). +- 주의: "연습 시작" 라우팅은 이미 고침(navigate(`/learn/session/:personaCode`)) — 빈 상태에서도 CTA는 살려야. + +### 2. 음성 입력 — `services/voice.py` + `routes/voice.py`(WSS) + `Session.tsx` 마이크 +윤찬: "크롬으로 하니까 내 음성이 안 들어감. 브라우저 어떻게 해야하는지 해야함." +- (a) 크롬 **마이크 권한** — HTTPS(vignette.chanpaca.net)는 OK, getUserMedia 권한 요청 UI 필요 +- (b) **음성 파이프라인 실연동** — STT(OpenAI whisper) → orchestrator turn → TTS. WSS `/api/voice/ws`(Caddyfile passthrough 있음). Session.tsx 마이크 버튼이 현재 UI만 — WSS 연동 필요. +- ⚠️ **OpenAI 키 필요**: 현재 `.env`/API env의 `OPENAI_API_KEY`가 dummy. 윤찬에게 실키 받아야 STT/TTS 동작. 키 없으면 services/voice.py가 degraded(501/503). + +## 외부 블로커 (자율 불가) +- **n=1 실 임상 축어록**: 한신대 교수 회신 필요. 요청 메일초안 = `Projects/영업/2026/한신대학교 산학협력 프로젝트/축어록_추가요청_메일초안.md` (윤찬 발송 대기). 합성 데이터로 개발 단계는 완화함. + +## 핵심 함정/패턴 (꼭 지킬 것) +- **빌드는 반드시 node22** — node23.4.0은 vite **segfault**(출력 0줄). PowerShell: `fnm env --use-on-cd | Out-String | Invoke-Expression; fnm use 22.22.3` +- 프론트 빌드: `$env:VITE_API_BASE="https://api-vignette.chanpaca.net"; npm run build` +- 배포: `wrangler pages deploy dist --project-name vignette --branch main --commit-dirty=true` (먼저 `dist/_redirects`에 `/* /index.html 200`) +- **deployment 미리보기 URL은 CORS 불일치** → 검증은 production(vignette.chanpaca.net) URL로 +- 라이브 검증 도구: `apps/web/_pptr_flow.cjs` (puppeteer-core + 시스템 Chrome, mock auth 주입 후 풀흐름 클릭) — `node _pptr_flow.cjs "https://vignette.chanpaca.net" ` +- dev 인증 우회: `ENVIRONMENT=dev`면 쿠키 없어도 통과(deps.py). 프론트 mock auth = localStorage `vignette.dev-auth` +- 한글 JSON은 **python httpx로** 보낼 것(curl -d 한글 인코딩 깨짐) +- Cloudflare 토큰: wrangler oauth(`%APPDATA%\xdg.config\.wrangler\config\default.toml`) / DNS 권한은 cloudflared `cert.pem`의 ARGO TOKEN apiToken + +## 윤찬 작업방식 (위반 주의) +- **완료보고 불신** — 실화면 인터랙션(puppeteer 클릭)까지 검증 후 보고. CORS/API 200만으론 "완료" 금지. +- **목업 싫어함** — 가짜 데이터로 화면 채우지 말 것. 빈 상태/실데이터. +- **디코로 답변 필수** — chat_id 1485472826118115338, inbound는 reply로. +- 위험은 한 번 알리고 주저말고 진행(확인 반복 금지). 단 Docker 같은 명시 가드는 존중.